diff options
Diffstat (limited to 'roms/u-boot/test/dm')
95 files changed, 17483 insertions, 0 deletions
diff --git a/roms/u-boot/test/dm/Kconfig b/roms/u-boot/test/dm/Kconfig new file mode 100644 index 000000000..e5b341e52 --- /dev/null +++ b/roms/u-boot/test/dm/Kconfig @@ -0,0 +1,8 @@ +config UT_DM + bool "Enable driver model unit test command" + depends on SANDBOX && UNIT_TEST + help + This enables the 'ut dm' command which runs a series of unit + tests on the driver model code. Each subsystem (uclass) is tested. + If all is well then all tests pass although there will be a few + messages printed along the way. diff --git a/roms/u-boot/test/dm/Makefile b/roms/u-boot/test/dm/Makefile new file mode 100644 index 000000000..c9644617a --- /dev/null +++ b/roms/u-boot/test/dm/Makefile @@ -0,0 +1,107 @@ +# SPDX-License-Identifier: GPL-2.0+ +# +# Copyright (c) 2013 Google, Inc + +obj-$(CONFIG_UT_DM) += test-dm.o + +# Tests for particular subsystems - when enabling driver model for a new +# subsystem you must add sandbox tests here. +ifeq ($(CONFIG_SPL_BUILD),y) +obj-$(CONFIG_SPL_OF_PLATDATA) += of_platdata.o +else +obj-$(CONFIG_UT_DM) += bus.o +obj-$(CONFIG_UT_DM) += test-driver.o +obj-$(CONFIG_UT_DM) += test-fdt.o +obj-$(CONFIG_UT_DM) += test-uclass.o + +obj-$(CONFIG_UT_DM) += core.o +obj-$(CONFIG_UT_DM) += read.o +obj-$(CONFIG_UT_DM) += phys2bus.o +ifneq ($(CONFIG_SANDBOX),) +obj-$(CONFIG_ACPIGEN) += acpi.o +obj-$(CONFIG_ACPIGEN) += acpigen.o +obj-$(CONFIG_ACPIGEN) += acpi_dp.o +obj-$(CONFIG_ADC) += adc.o +obj-$(CONFIG_SOUND) += audio.o +obj-$(CONFIG_AXI) += axi.o +obj-$(CONFIG_BLK) += blk.o +obj-$(CONFIG_BUTTON) += button.o +obj-$(CONFIG_DM_BOOTCOUNT) += bootcount.o +obj-$(CONFIG_CLK) += clk.o clk_ccf.o +obj-$(CONFIG_CPU) += cpu.o +obj-$(CONFIG_CROS_EC) += cros_ec.o +obj-$(CONFIG_DEVRES) += devres.o +obj-$(CONFIG_DMA) += dma.o +obj-$(CONFIG_VIDEO_MIPI_DSI) += dsi_host.o +obj-$(CONFIG_DM_DSA) += dsa.o +obj-$(CONFIG_DM_ETH) += eth.o +ifneq ($(CONFIG_EFI_PARTITION),) +obj-$(CONFIG_FASTBOOT_FLASH_MMC) += fastboot.o +endif +obj-$(CONFIG_FIRMWARE) += firmware.o +obj-$(CONFIG_DM_GPIO) += gpio.o +obj-$(CONFIG_DM_HWSPINLOCK) += hwspinlock.o +obj-$(CONFIG_DM_I2C) += i2c.o +obj-$(CONFIG_SOUND) += i2s.o +obj-y += irq.o +obj-$(CONFIG_CLK_K210_SET_RATE) += k210_pll.o +obj-$(CONFIG_LED) += led.o +obj-$(CONFIG_DM_MAILBOX) += mailbox.o +obj-$(CONFIG_DM_MDIO) += mdio.o +obj-$(CONFIG_DM_MDIO_MUX) += mdio_mux.o +obj-$(CONFIG_MISC) += misc.o +obj-$(CONFIG_DM_MMC) += mmc.o +obj-$(CONFIG_CMD_MUX) += mux-cmd.o +obj-$(CONFIG_MULTIPLEXER) += mux-emul.o +obj-$(CONFIG_MUX_MMIO) += mux-mmio.o +obj-y += fdtdec.o +obj-$(CONFIG_UT_DM) += nop.o +obj-y += ofnode.o +obj-y += ofread.o +obj-y += of_extra.o +obj-$(CONFIG_OSD) += osd.o +obj-$(CONFIG_DM_VIDEO) += panel.o +obj-$(CONFIG_EFI_PARTITION) += part.o +obj-$(CONFIG_DM_PCI) += pci.o +obj-$(CONFIG_P2SB) += p2sb.o +obj-$(CONFIG_PCI_ENDPOINT) += pci_ep.o +obj-$(CONFIG_PCH) += pch.o +obj-$(CONFIG_PHY) += phy.o +ifneq ($(CONFIG_PINMUX),) +obj-$(CONFIG_PINCONF) += pinmux.o +endif +obj-$(CONFIG_POWER_DOMAIN) += power-domain.o +obj-$(CONFIG_ACPI_PMC) += pmc.o +obj-$(CONFIG_DM_PMIC) += pmic.o +obj-$(CONFIG_DM_PWM) += pwm.o +obj-$(CONFIG_QFW) += qfw.o +obj-$(CONFIG_RAM) += ram.o +obj-y += regmap.o +obj-$(CONFIG_REMOTEPROC) += remoteproc.o +obj-$(CONFIG_DM_RESET) += reset.o +obj-$(CONFIG_SYSRESET) += sysreset.o +obj-$(CONFIG_DM_REGULATOR) += regulator.o +obj-$(CONFIG_DM_RNG) += rng.o +obj-$(CONFIG_DM_RTC) += rtc.o +obj-$(CONFIG_SCMI_FIRMWARE) += scmi.o +obj-$(CONFIG_DM_SERIAL) += serial.o +obj-$(CONFIG_DM_SPI_FLASH) += sf.o +obj-$(CONFIG_SIMPLE_BUS) += simple-bus.o +obj-$(CONFIG_SIMPLE_PM_BUS) += simple-pm-bus.o +obj-$(CONFIG_SMEM) += smem.o +obj-$(CONFIG_SOC_DEVICE) += soc.o +obj-$(CONFIG_SOUND) += sound.o +obj-$(CONFIG_DM_SPI) += spi.o +obj-$(CONFIG_SPMI) += spmi.o +obj-y += syscon.o +obj-$(CONFIG_RESET_SYSCON) += syscon-reset.o +obj-$(CONFIG_SYSINFO) += sysinfo.o +obj-$(CONFIG_SYSINFO_GPIO) += sysinfo-gpio.o +obj-$(CONFIG_TEE) += tee.o +obj-$(CONFIG_TIMER) += timer.o +obj-$(CONFIG_DM_USB) += usb.o +obj-$(CONFIG_DM_VIDEO) += video.o +obj-$(CONFIG_VIRTIO_SANDBOX) += virtio.o +obj-$(CONFIG_WDT) += wdt.o +endif +endif # !SPL diff --git a/roms/u-boot/test/dm/acpi.c b/roms/u-boot/test/dm/acpi.c new file mode 100644 index 000000000..2edab7be5 --- /dev/null +++ b/roms/u-boot/test/dm/acpi.c @@ -0,0 +1,569 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Tests for ACPI table generation + * + * Copyright 2019 Google LLC + * Written by Simon Glass <sjg@chromium.org> + */ + +#include <common.h> +#include <console.h> +#include <dm.h> +#include <malloc.h> +#include <mapmem.h> +#include <version.h> +#include <tables_csum.h> +#include <version.h> +#include <acpi/acpigen.h> +#include <acpi/acpi_device.h> +#include <acpi/acpi_table.h> +#include <asm/global_data.h> +#include <dm/acpi.h> +#include <dm/test.h> +#include <test/ut.h> +#include "acpi.h" + +#define BUF_SIZE 4096 + +/** + * struct testacpi_plat - Platform data for the test ACPI device + * + * @no_name: true to emit an empty ACPI name from testacpi_get_name() + * @return_error: true to return an error instead of a name + */ +struct testacpi_plat { + bool return_error; + bool no_name; +}; + +static int testacpi_write_tables(const struct udevice *dev, + struct acpi_ctx *ctx) +{ + struct acpi_dmar *dmar; + int ret; + + dmar = (struct acpi_dmar *)ctx->current; + acpi_create_dmar(dmar, DMAR_INTR_REMAP); + ctx->current += sizeof(struct acpi_dmar); + ret = acpi_add_table(ctx, dmar); + if (ret) + return log_msg_ret("add", ret); + + return 0; +} + +static int testacpi_get_name(const struct udevice *dev, char *out_name) +{ + struct testacpi_plat *plat = dev_get_plat(dev); + + if (plat->return_error) + return -EINVAL; + if (plat->no_name) { + *out_name = '\0'; + return 0; + } + if (device_get_uclass_id(dev->parent) == UCLASS_TEST_ACPI) + return acpi_copy_name(out_name, ACPI_TEST_CHILD_NAME); + else + return acpi_copy_name(out_name, ACPI_TEST_DEV_NAME); +} + +static int testacpi_fill_ssdt(const struct udevice *dev, struct acpi_ctx *ctx) +{ + const char *data; + + data = dev_read_string(dev, "acpi-ssdt-test-data"); + if (data) { + while (*data) + acpigen_emit_byte(ctx, *data++); + } + + return 0; +} + +static int testacpi_inject_dsdt(const struct udevice *dev, struct acpi_ctx *ctx) +{ + const char *data; + + data = dev_read_string(dev, "acpi-dsdt-test-data"); + if (data) { + while (*data) + acpigen_emit_byte(ctx, *data++); + } + + return 0; +} + +struct acpi_ops testacpi_ops = { + .get_name = testacpi_get_name, + .write_tables = testacpi_write_tables, + .fill_ssdt = testacpi_fill_ssdt, + .inject_dsdt = testacpi_inject_dsdt, +}; + +static const struct udevice_id testacpi_ids[] = { + { .compatible = "denx,u-boot-acpi-test" }, + { } +}; + +U_BOOT_DRIVER(testacpi_drv) = { + .name = "testacpi_drv", + .of_match = testacpi_ids, + .id = UCLASS_TEST_ACPI, + .bind = dm_scan_fdt_dev, + .plat_auto = sizeof(struct testacpi_plat), + ACPI_OPS_PTR(&testacpi_ops) +}; + +UCLASS_DRIVER(testacpi) = { + .name = "testacpi", + .id = UCLASS_TEST_ACPI, +}; + +/* Test ACPI get_name() */ +static int dm_test_acpi_get_name(struct unit_test_state *uts) +{ + char name[ACPI_NAME_MAX]; + struct udevice *dev, *dev2, *i2c, *spi, *timer, *sound; + struct udevice *pci, *root; + + /* Test getting the name from the driver */ + ut_assertok(uclass_first_device_err(UCLASS_TEST_ACPI, &dev)); + ut_assertok(acpi_get_name(dev, name)); + ut_asserteq_str(ACPI_TEST_DEV_NAME, name); + + /* Test getting the name from the device tree */ + ut_assertok(uclass_get_device_by_name(UCLASS_TEST_FDT, "a-test", + &dev2)); + ut_assertok(acpi_get_name(dev2, name)); + ut_asserteq_str("GHIJ", name); + + /* Test getting the name from acpi_device_get_name() */ + ut_assertok(uclass_first_device(UCLASS_I2C, &i2c)); + ut_assertok(acpi_get_name(i2c, name)); + ut_asserteq_str("I2C0", name); + + ut_assertok(uclass_first_device(UCLASS_SPI, &spi)); + ut_assertok(acpi_get_name(spi, name)); + ut_asserteq_str("SPI0", name); + + /* ACPI doesn't know about the timer */ + ut_assertok(uclass_first_device(UCLASS_TIMER, &timer)); + ut_asserteq(-ENOENT, acpi_get_name(timer, name)); + + /* May as well test the rest of the cases */ + ut_assertok(uclass_first_device(UCLASS_SOUND, &sound)); + ut_assertok(acpi_get_name(sound, name)); + ut_asserteq_str("HDAS", name); + + ut_assertok(uclass_first_device(UCLASS_PCI, &pci)); + ut_assertok(acpi_get_name(pci, name)); + ut_asserteq_str("PCI0", name); + + ut_assertok(uclass_first_device(UCLASS_ROOT, &root)); + ut_assertok(acpi_get_name(root, name)); + ut_asserteq_str("\\_SB", name); + + /* Note that we don't have tests for acpi_name_from_id() */ + + return 0; +} +DM_TEST(dm_test_acpi_get_name, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); + +/* Test acpi_get_table_revision() */ +static int dm_test_acpi_get_table_revision(struct unit_test_state *uts) +{ + ut_asserteq(1, acpi_get_table_revision(ACPITAB_MCFG)); + ut_asserteq(2, acpi_get_table_revision(ACPITAB_RSDP)); + ut_asserteq(4, acpi_get_table_revision(ACPITAB_TPM2)); + ut_asserteq(-EINVAL, acpi_get_table_revision(ACPITAB_COUNT)); + + return 0; +} +DM_TEST(dm_test_acpi_get_table_revision, + UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); + +/* Test acpi_create_dmar() */ +static int dm_test_acpi_create_dmar(struct unit_test_state *uts) +{ + struct acpi_dmar dmar; + struct udevice *cpu; + + ut_assertok(uclass_first_device(UCLASS_CPU, &cpu)); + ut_assertnonnull(cpu); + ut_assertok(acpi_create_dmar(&dmar, DMAR_INTR_REMAP)); + ut_asserteq(DMAR_INTR_REMAP, dmar.flags); + ut_asserteq(32 - 1, dmar.host_address_width); + + return 0; +} +DM_TEST(dm_test_acpi_create_dmar, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); + +/* Test acpi_fill_header() */ +static int dm_test_acpi_fill_header(struct unit_test_state *uts) +{ + struct acpi_table_header hdr; + + /* Make sure these 5 fields are not changed */ + hdr.length = 0x11; + hdr.revision = 0x22; + hdr.checksum = 0x33; + hdr.aslc_revision = 0x44; + acpi_fill_header(&hdr, "ABCD"); + + ut_asserteq_mem("ABCD", hdr.signature, sizeof(hdr.signature)); + ut_asserteq(0x11, hdr.length); + ut_asserteq(0x22, hdr.revision); + ut_asserteq(0x33, hdr.checksum); + ut_asserteq_mem(OEM_ID, hdr.oem_id, sizeof(hdr.oem_id)); + ut_asserteq_mem(OEM_TABLE_ID, hdr.oem_table_id, + sizeof(hdr.oem_table_id)); + ut_asserteq(U_BOOT_BUILD_DATE, hdr.oem_revision); + ut_asserteq_mem(ASLC_ID, hdr.aslc_id, sizeof(hdr.aslc_id)); + ut_asserteq(0x44, hdr.aslc_revision); + + return 0; +} +DM_TEST(dm_test_acpi_fill_header, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); + +/* Test ACPI write_tables() */ +static int dm_test_acpi_write_tables(struct unit_test_state *uts) +{ + struct acpi_dmar *dmar; + struct acpi_ctx ctx; + void *buf; + int i; + + buf = malloc(BUF_SIZE); + ut_assertnonnull(buf); + + acpi_setup_base_tables(&ctx, buf); + dmar = ctx.current; + ut_assertok(acpi_write_dev_tables(&ctx)); + + /* + * We should have three dmar tables, one for each + * "denx,u-boot-acpi-test" device + */ + ut_asserteq_ptr(dmar + 3, ctx.current); + ut_asserteq(DMAR_INTR_REMAP, dmar->flags); + ut_asserteq(32 - 1, dmar->host_address_width); + + ut_asserteq(DMAR_INTR_REMAP, dmar[1].flags); + ut_asserteq(32 - 1, dmar[1].host_address_width); + + ut_asserteq(DMAR_INTR_REMAP, dmar[2].flags); + ut_asserteq(32 - 1, dmar[2].host_address_width); + + /* Check that the pointers were added correctly */ + for (i = 0; i < 3; i++) { + ut_asserteq(map_to_sysmem(dmar + i), ctx.rsdt->entry[i]); + ut_asserteq(map_to_sysmem(dmar + i), ctx.xsdt->entry[i]); + } + ut_asserteq(0, ctx.rsdt->entry[3]); + ut_asserteq(0, ctx.xsdt->entry[3]); + + return 0; +} +DM_TEST(dm_test_acpi_write_tables, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); + +/* Test basic ACPI functions */ +static int dm_test_acpi_basic(struct unit_test_state *uts) +{ + struct acpi_ctx ctx; + + /* Check align works */ + ctx.current = (void *)5; + acpi_align(&ctx); + ut_asserteq_ptr((void *)16, ctx.current); + + /* Check that align does nothing if already aligned */ + acpi_align(&ctx); + ut_asserteq_ptr((void *)16, ctx.current); + acpi_align64(&ctx); + ut_asserteq_ptr((void *)64, ctx.current); + acpi_align64(&ctx); + ut_asserteq_ptr((void *)64, ctx.current); + + /* Check incrementing */ + acpi_inc(&ctx, 3); + ut_asserteq_ptr((void *)67, ctx.current); + acpi_inc_align(&ctx, 3); + ut_asserteq_ptr((void *)80, ctx.current); + + return 0; +} +DM_TEST(dm_test_acpi_basic, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); + +/* Test acpi_setup_base_tables */ +static int dm_test_acpi_setup_base_tables(struct unit_test_state *uts) +{ + struct acpi_rsdp *rsdp; + struct acpi_rsdt *rsdt; + struct acpi_xsdt *xsdt; + struct acpi_ctx ctx; + void *buf, *end; + + /* + * Use an unaligned address deliberately, by allocating an aligned + * address and then adding 4 to it + */ + buf = memalign(64, BUF_SIZE); + ut_assertnonnull(buf); + acpi_setup_base_tables(&ctx, buf + 4); + ut_asserteq(map_to_sysmem(PTR_ALIGN(buf + 4, 16)), gd->arch.acpi_start); + + rsdp = buf + 16; + ut_asserteq_ptr(rsdp, ctx.rsdp); + ut_asserteq_mem(RSDP_SIG, rsdp->signature, sizeof(rsdp->signature)); + ut_asserteq(sizeof(*rsdp), rsdp->length); + ut_assertok(table_compute_checksum(rsdp, 20)); + ut_assertok(table_compute_checksum(rsdp, sizeof(*rsdp))); + + rsdt = PTR_ALIGN((void *)rsdp + sizeof(*rsdp), 16); + ut_asserteq_ptr(rsdt, ctx.rsdt); + ut_asserteq_mem("RSDT", rsdt->header.signature, ACPI_NAME_LEN); + ut_asserteq(sizeof(*rsdt), rsdt->header.length); + ut_assertok(table_compute_checksum(rsdt, sizeof(*rsdt))); + + xsdt = PTR_ALIGN((void *)rsdt + sizeof(*rsdt), 16); + ut_asserteq_ptr(xsdt, ctx.xsdt); + ut_asserteq_mem("XSDT", xsdt->header.signature, ACPI_NAME_LEN); + ut_asserteq(sizeof(*xsdt), xsdt->header.length); + ut_assertok(table_compute_checksum(xsdt, sizeof(*xsdt))); + + end = PTR_ALIGN((void *)xsdt + sizeof(*xsdt), 64); + ut_asserteq_ptr(end, ctx.current); + + ut_asserteq(map_to_sysmem(rsdt), rsdp->rsdt_address); + ut_asserteq(map_to_sysmem(xsdt), rsdp->xsdt_address); + + return 0; +} +DM_TEST(dm_test_acpi_setup_base_tables, + UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); + +/* Test 'acpi list' command */ +static int dm_test_acpi_cmd_list(struct unit_test_state *uts) +{ + struct acpi_ctx ctx; + ulong addr; + void *buf; + + buf = memalign(16, BUF_SIZE); + ut_assertnonnull(buf); + acpi_setup_base_tables(&ctx, buf); + + ut_assertok(acpi_write_dev_tables(&ctx)); + + console_record_reset(); + run_command("acpi list", 0); + addr = (ulong)map_to_sysmem(buf); + ut_assert_nextline("ACPI tables start at %lx", addr); + ut_assert_nextline("RSDP %08lx %06zx (v02 U-BOOT)", addr, + sizeof(struct acpi_rsdp)); + addr = ALIGN(addr + sizeof(struct acpi_rsdp), 16); + ut_assert_nextline("RSDT %08lx %06zx (v01 U-BOOT U-BOOTBL %x INTL 0)", + addr, sizeof(struct acpi_table_header) + + 3 * sizeof(u32), U_BOOT_BUILD_DATE); + addr = ALIGN(addr + sizeof(struct acpi_rsdt), 16); + ut_assert_nextline("XSDT %08lx %06zx (v01 U-BOOT U-BOOTBL %x INTL 0)", + addr, sizeof(struct acpi_table_header) + + 3 * sizeof(u64), U_BOOT_BUILD_DATE); + addr = ALIGN(addr + sizeof(struct acpi_xsdt), 64); + ut_assert_nextline("DMAR %08lx %06zx (v01 U-BOOT U-BOOTBL %x INTL 0)", + addr, sizeof(struct acpi_dmar), U_BOOT_BUILD_DATE); + addr = ALIGN(addr + sizeof(struct acpi_dmar), 16); + ut_assert_nextline("DMAR %08lx %06zx (v01 U-BOOT U-BOOTBL %x INTL 0)", + addr, sizeof(struct acpi_dmar), U_BOOT_BUILD_DATE); + addr = ALIGN(addr + sizeof(struct acpi_dmar), 16); + ut_assert_nextline("DMAR %08lx %06zx (v01 U-BOOT U-BOOTBL %x INTL 0)", + addr, sizeof(struct acpi_dmar), U_BOOT_BUILD_DATE); + ut_assert_console_end(); + + return 0; +} +DM_TEST(dm_test_acpi_cmd_list, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); + +/* Test 'acpi dump' command */ +static int dm_test_acpi_cmd_dump(struct unit_test_state *uts) +{ + struct acpi_ctx ctx; + ulong addr; + void *buf; + + buf = memalign(16, BUF_SIZE); + ut_assertnonnull(buf); + acpi_setup_base_tables(&ctx, buf); + + ut_assertok(acpi_write_dev_tables(&ctx)); + + /* First search for a non-existent table */ + console_record_reset(); + run_command("acpi dump rdst", 0); + ut_assert_nextline("Table 'RDST' not found"); + ut_assert_console_end(); + + /* Now a real table */ + console_record_reset(); + run_command("acpi dump dmar", 0); + addr = ALIGN(map_to_sysmem(ctx.xsdt) + sizeof(struct acpi_xsdt), 64); + ut_assert_nextline("DMAR @ %08lx", addr); + ut_assert_nextlines_are_dump(0x30); + ut_assert_console_end(); + + return 0; +} +DM_TEST(dm_test_acpi_cmd_dump, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); + +/* Test acpi_device_path() */ +static int dm_test_acpi_device_path(struct unit_test_state *uts) +{ + struct testacpi_plat *plat; + char buf[ACPI_PATH_MAX]; + struct udevice *dev, *child; + + ut_assertok(uclass_first_device_err(UCLASS_TEST_ACPI, &dev)); + ut_assertok(acpi_device_path(dev, buf, sizeof(buf))); + ut_asserteq_str("\\_SB." ACPI_TEST_DEV_NAME, buf); + + /* Test running out of space */ + buf[5] = '\0'; + ut_asserteq(-ENOSPC, acpi_device_path(dev, buf, 5)); + ut_asserteq('\0', buf[5]); + + /* Test a three-component name */ + ut_assertok(device_first_child_err(dev, &child)); + ut_assertok(acpi_device_path(child, buf, sizeof(buf))); + ut_asserteq_str("\\_SB." ACPI_TEST_DEV_NAME "." ACPI_TEST_CHILD_NAME, + buf); + + /* Test handling of a device which doesn't produce a name */ + plat = dev_get_plat(dev); + plat->no_name = true; + ut_assertok(acpi_device_path(child, buf, sizeof(buf))); + ut_asserteq_str("\\_SB." ACPI_TEST_CHILD_NAME, buf); + + /* Test handling of a device which returns an error */ + plat = dev_get_plat(dev); + plat->return_error = true; + ut_asserteq(-EINVAL, acpi_device_path(child, buf, sizeof(buf))); + + return 0; +} +DM_TEST(dm_test_acpi_device_path, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); + +/* Test acpi_device_status() */ +static int dm_test_acpi_device_status(struct unit_test_state *uts) +{ + struct udevice *dev; + + ut_assertok(uclass_first_device_err(UCLASS_TEST_ACPI, &dev)); + ut_asserteq(ACPI_DSTATUS_ALL_ON, acpi_device_status(dev)); + + return 0; +} +DM_TEST(dm_test_acpi_device_status, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); + +/* Test acpi_fill_ssdt() */ +static int dm_test_acpi_fill_ssdt(struct unit_test_state *uts) +{ + struct acpi_ctx ctx; + u8 *buf; + + buf = malloc(BUF_SIZE); + ut_assertnonnull(buf); + + acpi_reset_items(); + ctx.current = buf; + buf[4] = 'z'; /* sentinel */ + ut_assertok(acpi_fill_ssdt(&ctx)); + + /* + * These values come from acpi-test2's acpi-ssdt-test-data property. + * This device comes first because of u-boot,acpi-ssdt-order + */ + ut_asserteq('c', buf[0]); + ut_asserteq('d', buf[1]); + + /* These values come from acpi-test's acpi-ssdt-test-data property */ + ut_asserteq('a', buf[2]); + ut_asserteq('b', buf[3]); + + ut_asserteq('z', buf[4]); + + return 0; +} +DM_TEST(dm_test_acpi_fill_ssdt, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); + +/* Test acpi_inject_dsdt() */ +static int dm_test_acpi_inject_dsdt(struct unit_test_state *uts) +{ + struct acpi_ctx ctx; + u8 *buf; + + buf = malloc(BUF_SIZE); + ut_assertnonnull(buf); + + acpi_reset_items(); + ctx.current = buf; + buf[4] = 'z'; /* sentinel */ + ut_assertok(acpi_inject_dsdt(&ctx)); + + /* + * These values come from acpi-test's acpi-dsdt-test-data property. + * There is no u-boot,acpi-dsdt-order so device-tree order is used. + */ + ut_asserteq('h', buf[0]); + ut_asserteq('i', buf[1]); + + /* These values come from acpi-test's acpi-dsdt-test-data property */ + ut_asserteq('j', buf[2]); + ut_asserteq('k', buf[3]); + + ut_asserteq('z', buf[4]); + + return 0; +} +DM_TEST(dm_test_acpi_inject_dsdt, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); + +/* Test 'acpi items' command */ +static int dm_test_acpi_cmd_items(struct unit_test_state *uts) +{ + struct acpi_ctx ctx; + void *buf; + + buf = malloc(BUF_SIZE); + ut_assertnonnull(buf); + + acpi_reset_items(); + ctx.current = buf; + ut_assertok(acpi_fill_ssdt(&ctx)); + console_record_reset(); + run_command("acpi items", 0); + ut_assert_nextline("dev 'acpi-test', type 1, size 2"); + ut_assert_nextline("dev 'acpi-test2', type 1, size 2"); + ut_assert_console_end(); + + acpi_reset_items(); + ctx.current = buf; + ut_assertok(acpi_inject_dsdt(&ctx)); + console_record_reset(); + run_command("acpi items", 0); + ut_assert_nextline("dev 'acpi-test', type 2, size 2"); + ut_assert_nextline("dev 'acpi-test2', type 2, size 2"); + ut_assert_console_end(); + + console_record_reset(); + run_command("acpi items -d", 0); + ut_assert_nextline("dev 'acpi-test', type 2, size 2"); + ut_assert_nextlines_are_dump(2); + ut_assert_nextline("%s", ""); + ut_assert_nextline("dev 'acpi-test2', type 2, size 2"); + ut_assert_nextlines_are_dump(2); + ut_assert_nextline("%s", ""); + ut_assert_console_end(); + + return 0; +} +DM_TEST(dm_test_acpi_cmd_items, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); diff --git a/roms/u-boot/test/dm/acpi.h b/roms/u-boot/test/dm/acpi.h new file mode 100644 index 000000000..535db56b5 --- /dev/null +++ b/roms/u-boot/test/dm/acpi.h @@ -0,0 +1,32 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Common functions for ACPI tests + * + * Copyright 2020 Google LLC + * Written by Simon Glass <sjg@chromium.org> + */ + +#ifndef __TEST_DM_ACPI_H +#define __TEST_DM_ACPI_H + +#define ACPI_TEST_DEV_NAME "ABCD" +#define ACPI_TEST_CHILD_NAME "EFGH" + +/** + * acpi_test_alloc_context_size() - Allocate an ACPI context of a given size + * + * @ctxp: Returns allocated context + * @size: Size to allocate in bytes + * @return 0 if OK, -ENOMEM if out of memory + */ +int acpi_test_alloc_context_size(struct acpi_ctx **ctxp, int size); + +/** + * acpi_test_get_length() - decode a three-byte length field + * + * @ptr: Length encoded as per ACPI + * @return decoded length, or -EINVAL on error + */ +int acpi_test_get_length(u8 *ptr); + +#endif /*__TEST_DM_ACPI_H */ diff --git a/roms/u-boot/test/dm/acpi_dp.c b/roms/u-boot/test/dm/acpi_dp.c new file mode 100644 index 000000000..44bcabda6 --- /dev/null +++ b/roms/u-boot/test/dm/acpi_dp.c @@ -0,0 +1,492 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Tests for ACPI code generation via a device-property table + * + * Copyright 2019 Google LLC + * Written by Simon Glass <sjg@chromium.org> + */ + +#include <common.h> +#include <dm.h> +#include <uuid.h> +#include <acpi/acpigen.h> +#include <acpi/acpi_dp.h> +#include <asm/unaligned.h> +#include <dm/acpi.h> +#include <dm/test.h> +#include <test/ut.h> +#include "acpi.h" + +/* Maximum size of the ACPI context needed for most tests */ +#define ACPI_CONTEXT_SIZE 500 + +#define TEST_INT8 0x7d +#define TEST_INT16 0x2345 +#define TEST_INT32 0x12345678 +#define TEST_INT64 0x4567890123456 +#define TEST_STR "testing acpi strings" +#define TEST_REF "\\SB.I2C0.TPM2" +#define EXPECT_REF "SB__I2C0TPM2" + +static int alloc_context(struct acpi_ctx **ctxp) +{ + return acpi_test_alloc_context_size(ctxp, ACPI_CONTEXT_SIZE); + + return 0; +} + +static void free_context(struct acpi_ctx **ctxp) +{ + free(*ctxp); + *ctxp = NULL; +} + +/* Test emitting an empty table */ +static int dm_test_acpi_dp_new_table(struct unit_test_state *uts) +{ + struct acpi_ctx *ctx; + struct acpi_dp *dp; + u8 *ptr; + + ut_assertok(alloc_context(&ctx)); + + dp = acpi_dp_new_table("FRED"); + ut_assertnonnull(dp); + + ptr = acpigen_get_current(ctx); + ut_assertok(acpi_dp_write(ctx, dp)); + ut_asserteq(10, acpigen_get_current(ctx) - ptr); + ut_asserteq(NAME_OP, *(u8 *)ptr); + ut_asserteq_strn("FRED", (char *)ptr + 1); + ut_asserteq(PACKAGE_OP, ptr[5]); + ut_asserteq(4, acpi_test_get_length(ptr + 6)); + ut_asserteq(0, ptr[9]); + + free_context(&ctx); + + return 0; +} +DM_TEST(dm_test_acpi_dp_new_table, 0); + +/* Test emitting an integer */ +static int dm_test_acpi_dp_int(struct unit_test_state *uts) +{ + struct acpi_ctx *ctx; + char uuid[UUID_STR_LEN + 1]; + struct acpi_dp *dp; + u8 *ptr; + + ut_assertok(alloc_context(&ctx)); + + dp = acpi_dp_new_table("FRED"); + ut_assertnonnull(dp); + ut_assertnonnull(acpi_dp_add_integer(dp, "MARY", TEST_INT32)); + + ptr = acpigen_get_current(ctx); + ut_assertok(acpi_dp_write(ctx, dp)); + ut_asserteq(54, acpigen_get_current(ctx) - ptr); + ut_asserteq(NAME_OP, *(u8 *)ptr); + ut_asserteq_strn("FRED", (char *)ptr + 1); + ut_asserteq(PACKAGE_OP, ptr[5]); + ut_asserteq(48, acpi_test_get_length(ptr + 6)); + ut_asserteq(2, ptr[9]); + + /* UUID */ + ut_asserteq(BUFFER_OP, ptr[10]); + ut_asserteq(22, acpi_test_get_length(ptr + 11)); + ut_asserteq(WORD_PREFIX, ptr[14]); + ut_asserteq(16, get_unaligned((u16 *)(ptr + 15))); + uuid_bin_to_str(ptr + 17, uuid, 1); + ut_asserteq_str(ACPI_DP_UUID, uuid); + + /* Container package */ + ut_asserteq(PACKAGE_OP, ptr[33]); + ut_asserteq(20, acpi_test_get_length(ptr + 34)); + ut_asserteq(1, ptr[37]); + + /* Package with name and (integer) value */ + ut_asserteq(PACKAGE_OP, ptr[38]); + ut_asserteq(15, acpi_test_get_length(ptr + 39)); + ut_asserteq(2, ptr[42]); + ut_asserteq(STRING_PREFIX, ptr[43]); + ut_asserteq_str("MARY", (char *)ptr + 44); + + ut_asserteq(DWORD_PREFIX, ptr[49]); + ut_asserteq(TEST_INT32, get_unaligned((u32 *)(ptr + 50))); + + free_context(&ctx); + + return 0; +} +DM_TEST(dm_test_acpi_dp_int, 0); + +/* Test emitting a 64-bit integer */ +static int dm_test_acpi_dp_int64(struct unit_test_state *uts) +{ + struct acpi_ctx *ctx; + struct acpi_dp *dp; + u8 *ptr; + + ut_assertok(alloc_context(&ctx)); + + dp = acpi_dp_new_table("FRED"); + ut_assertnonnull(dp); + ut_assertnonnull(acpi_dp_add_integer(dp, "MARY", TEST_INT64)); + + ptr = acpigen_get_current(ctx); + ut_assertok(acpi_dp_write(ctx, dp)); + ut_asserteq(58, acpigen_get_current(ctx) - ptr); + + ut_asserteq(QWORD_PREFIX, ptr[49]); + ut_asserteq_64(TEST_INT64, get_unaligned((u64 *)(ptr + 50))); + + free_context(&ctx); + + return 0; +} +DM_TEST(dm_test_acpi_dp_int64, 0); + +/* Test emitting a 16-bit integer */ +static int dm_test_acpi_dp_int16(struct unit_test_state *uts) +{ + struct acpi_ctx *ctx; + struct acpi_dp *dp; + u8 *ptr; + + ut_assertok(alloc_context(&ctx)); + + dp = acpi_dp_new_table("FRED"); + ut_assertnonnull(dp); + ut_assertnonnull(acpi_dp_add_integer(dp, "MARY", TEST_INT16)); + + ptr = acpigen_get_current(ctx); + ut_assertok(acpi_dp_write(ctx, dp)); + ut_asserteq(52, acpigen_get_current(ctx) - ptr); + + ut_asserteq(WORD_PREFIX, ptr[49]); + ut_asserteq(TEST_INT16, get_unaligned((u16 *)(ptr + 50))); + + free_context(&ctx); + + return 0; +} +DM_TEST(dm_test_acpi_dp_int16, 0); + +/* Test emitting a 8-bit integer */ +static int dm_test_acpi_dp_int8(struct unit_test_state *uts) +{ + struct acpi_ctx *ctx; + struct acpi_dp *dp; + u8 *ptr; + + ut_assertok(alloc_context(&ctx)); + + dp = acpi_dp_new_table("FRED"); + ut_assertnonnull(dp); + ut_assertnonnull(acpi_dp_add_integer(dp, "MARY", TEST_INT8)); + + ptr = acpigen_get_current(ctx); + ut_assertok(acpi_dp_write(ctx, dp)); + ut_asserteq(51, acpigen_get_current(ctx) - ptr); + + ut_asserteq(BYTE_PREFIX, ptr[49]); + ut_asserteq(TEST_INT8, ptr[50]); + + free_context(&ctx); + + return 0; +} +DM_TEST(dm_test_acpi_dp_int8, 0); + +/* Test emitting multiple values */ +static int dm_test_acpi_dp_multiple(struct unit_test_state *uts) +{ + struct acpi_ctx *ctx; + struct acpi_dp *dp; + u8 *ptr; + + ut_assertok(alloc_context(&ctx)); + + dp = acpi_dp_new_table("FRED"); + ut_assertnonnull(dp); + ut_assertnonnull(acpi_dp_add_integer(dp, "int16", TEST_INT16)); + ut_assertnonnull(acpi_dp_add_string(dp, "str", TEST_STR)); + ut_assertnonnull(acpi_dp_add_reference(dp, "ref", TEST_REF)); + + ptr = acpigen_get_current(ctx); + ut_assertok(acpi_dp_write(ctx, dp)); + ut_asserteq(110, acpigen_get_current(ctx) - ptr); + + ut_asserteq(WORD_PREFIX, ptr[0x32]); + ut_asserteq(TEST_INT16, get_unaligned((u16 *)(ptr + 0x33))); + ut_asserteq(STRING_PREFIX, ptr[0x3f]); + ut_asserteq_str(TEST_STR, (char *)ptr + 0x40); + ut_asserteq(ROOT_PREFIX, ptr[0x5f]); + ut_asserteq(MULTI_NAME_PREFIX, ptr[0x60]); + ut_asserteq(3, ptr[0x61]); + ut_asserteq_strn(EXPECT_REF, (char *)ptr + 0x62); + + free_context(&ctx); + + return 0; +} +DM_TEST(dm_test_acpi_dp_multiple, 0); + +/* Test emitting an array */ +static int dm_test_acpi_dp_array(struct unit_test_state *uts) +{ + struct acpi_ctx *ctx; + struct acpi_dp *dp; + u64 speed[4]; + u8 *ptr; + + ut_assertok(alloc_context(&ctx)); + + dp = acpi_dp_new_table("FRED"); + ut_assertnonnull(dp); + speed[0] = TEST_INT8; + speed[1] = TEST_INT16; + speed[2] = TEST_INT32; + speed[3] = TEST_INT64; + ut_assertnonnull(acpi_dp_add_integer_array(dp, "speeds", speed, + ARRAY_SIZE(speed))); + + ptr = acpigen_get_current(ctx); + ut_assertok(acpi_dp_write(ctx, dp)); + ut_asserteq(75, acpigen_get_current(ctx) - ptr); + + ut_asserteq(BYTE_PREFIX, ptr[0x38]); + ut_asserteq(TEST_INT8, ptr[0x39]); + + ut_asserteq(WORD_PREFIX, ptr[0x3a]); + ut_asserteq(TEST_INT16, get_unaligned((u16 *)(ptr + 0x3b))); + + ut_asserteq(DWORD_PREFIX, ptr[0x3d]); + ut_asserteq(TEST_INT32, get_unaligned((u32 *)(ptr + 0x3e))); + + ut_asserteq(QWORD_PREFIX, ptr[0x42]); + ut_asserteq_64(TEST_INT64, get_unaligned((u64 *)(ptr + 0x43))); + + free_context(&ctx); + + return 0; +} +DM_TEST(dm_test_acpi_dp_array, 0); + +/* Test emitting a child */ +static int dm_test_acpi_dp_child(struct unit_test_state *uts) +{ + struct acpi_ctx *ctx; + struct acpi_dp *dp, *child1, *child2; + char uuid[UUID_STR_LEN + 1]; + u8 *ptr, *pptr; + int i; + + ut_assertok(alloc_context(&ctx)); + + child1 = acpi_dp_new_table("child"); + ut_assertnonnull(child1); + ut_assertnonnull(acpi_dp_add_integer(child1, "height", TEST_INT16)); + + child2 = acpi_dp_new_table("child"); + ut_assertnonnull(child2); + ut_assertnonnull(acpi_dp_add_integer(child2, "age", TEST_INT8)); + + dp = acpi_dp_new_table("FRED"); + ut_assertnonnull(dp); + + ut_assertnonnull(acpi_dp_add_child(dp, "anna", child1)); + ut_assertnonnull(acpi_dp_add_child(dp, "john", child2)); + + ptr = acpigen_get_current(ctx); + ut_assertok(acpi_dp_write(ctx, dp)); + ut_asserteq(178, acpigen_get_current(ctx) - ptr); + + /* UUID for child extension using Hierarchical Data Extension UUID */ + ut_asserteq(BUFFER_OP, ptr[10]); + ut_asserteq(22, acpi_test_get_length(ptr + 11)); + ut_asserteq(WORD_PREFIX, ptr[14]); + ut_asserteq(16, get_unaligned((u16 *)(ptr + 15))); + uuid_bin_to_str(ptr + 17, uuid, 1); + ut_asserteq_str(ACPI_DP_CHILD_UUID, uuid); + + /* Package with two children */ + ut_asserteq(PACKAGE_OP, ptr[0x21]); + ut_asserteq(0x28, acpi_test_get_length(ptr + 0x22)); + ut_asserteq(2, ptr[0x25]); + + /* First we expect the two children as string/value */ + pptr = ptr + 0x26; + for (i = 0; i < 2; i++) { + ut_asserteq(PACKAGE_OP, pptr[0]); + ut_asserteq(0x11, acpi_test_get_length(pptr + 1)); + ut_asserteq(2, pptr[4]); + ut_asserteq(STRING_PREFIX, pptr[5]); + ut_asserteq_str(i ? "john" : "anna", (char *)pptr + 6); + ut_asserteq(STRING_PREFIX, pptr[11]); + ut_asserteq_str("child", (char *)pptr + 12); + pptr += 0x12; + } + + /* Write the two children */ + ut_asserteq(0x4a, pptr - ptr); + for (i = 0; i < 2; i++) { + const char *prop = i ? "age" : "height"; + const int datalen = i ? 1 : 2; + int len = strlen(prop) + 1; + + ut_asserteq(NAME_OP, pptr[0]); + ut_asserteq_strn("chil", (char *)pptr + 1); + ut_asserteq(PACKAGE_OP, pptr[5]); + ut_asserteq(0x27 + len + datalen, acpi_test_get_length(pptr + 6)); + ut_asserteq(2, pptr[9]); + + /* UUID */ + ut_asserteq(BUFFER_OP, pptr[10]); + ut_asserteq(22, acpi_test_get_length(pptr + 11)); + ut_asserteq(WORD_PREFIX, pptr[14]); + ut_asserteq(16, get_unaligned((u16 *)(pptr + 15))); + uuid_bin_to_str(pptr + 17, uuid, 1); + ut_asserteq_str(ACPI_DP_UUID, uuid); + pptr += 33; + + /* Containing package */ + ut_asserteq(i ? 0xa1 : 0x6b, pptr - ptr); + ut_asserteq(PACKAGE_OP, pptr[0]); + ut_asserteq(0xb + len + datalen, acpi_test_get_length(pptr + 1)); + ut_asserteq(1, pptr[4]); + + /* Package containing the property-name string and the value */ + pptr += 5; + ut_asserteq(i ? 0xa6 : 0x70, pptr - ptr); + ut_asserteq(PACKAGE_OP, pptr[0]); + ut_asserteq(6 + len + datalen, acpi_test_get_length(pptr + 1)); + ut_asserteq(2, pptr[4]); + + ut_asserteq(STRING_PREFIX, pptr[5]); + ut_asserteq_str(i ? "age" : "height", (char *)pptr + 6); + pptr += 6 + len; + if (i) { + ut_asserteq(BYTE_PREFIX, pptr[0]); + ut_asserteq(TEST_INT8, pptr[1]); + } else { + ut_asserteq(WORD_PREFIX, pptr[0]); + ut_asserteq(TEST_INT16, + get_unaligned((u16 *)(pptr + 1))); + } + pptr += 1 + datalen; + } + ut_asserteq(178, pptr - ptr); + + free_context(&ctx); + + return 0; +} +DM_TEST(dm_test_acpi_dp_child, 0); + +/* Test emitting a GPIO */ +static int dm_test_acpi_dp_gpio(struct unit_test_state *uts) +{ + struct acpi_ctx *ctx; + struct acpi_dp *dp; + u8 *ptr, *pptr; + + ut_assertok(alloc_context(&ctx)); + + dp = acpi_dp_new_table("FRED"); + ut_assertnonnull(dp); + + /* Try a few different parameters */ + ut_assertnonnull(acpi_dp_add_gpio(dp, "reset", TEST_REF, 0x23, 0x24, + ACPI_GPIO_ACTIVE_HIGH)); + ut_assertnonnull(acpi_dp_add_gpio(dp, "allow", TEST_REF, 0, 0, + ACPI_GPIO_ACTIVE_LOW)); + + ptr = acpigen_get_current(ctx); + ut_assertok(acpi_dp_write(ctx, dp)); + ut_asserteq(0x6e, acpigen_get_current(ctx) - ptr); + + pptr = ptr + 0x2c; //0x3a; + ut_asserteq_str("reset", (char *)pptr); + ut_asserteq_strn(EXPECT_REF, (char *)pptr + 0xe); + ut_asserteq(0x23, pptr[0x1b]); + ut_asserteq(0x24, pptr[0x1d]); + ut_asserteq(ZERO_OP, pptr[0x1e]); + + pptr = ptr + 0x51; + ut_asserteq_str("allow", (char *)pptr); + ut_asserteq_strn(EXPECT_REF, (char *)pptr + 0xe); + ut_asserteq(ZERO_OP, pptr[0x1a]); + ut_asserteq(ZERO_OP, pptr[0x1b]); + ut_asserteq(ONE_OP, pptr[0x1c]); + + return 0; +} +DM_TEST(dm_test_acpi_dp_gpio, 0); + +/* Test copying info from the device tree to ACPI tables */ +static int dm_test_acpi_dp_copy(struct unit_test_state *uts) +{ + struct acpi_ctx *ctx; + struct udevice *dev; + struct acpi_dp *dp; + ofnode node; + u8 *ptr; + + ut_assertok(alloc_context(&ctx)); + + dp = acpi_dp_new_table("FRED"); + ut_assertnonnull(dp); + + ut_assertok(uclass_get_device(UCLASS_TEST_FDT, 0, &dev)); + ut_asserteq_str("a-test", dev->name); + + ut_assertok(acpi_dp_dev_copy_int(dev, dp, "int-value")); + ut_asserteq(-EINVAL, acpi_dp_dev_copy_int(dev, dp, "missing-value")); + ut_assertok(acpi_dp_dev_copy_int(dev, dp, "uint-value")); + + ut_assertok(acpi_dp_dev_copy_str(dev, dp, "str-value")); + ut_asserteq(-EINVAL, acpi_dp_dev_copy_str(dev, dp, "missing-value")); + + node = ofnode_path("/chosen"); + ut_assert(ofnode_valid(node)); + ut_assertok(acpi_dp_ofnode_copy_int(node, dp, "int-values")); + ut_asserteq(-EINVAL, + acpi_dp_ofnode_copy_int(node, dp, "missing-value")); + + ut_assertok(acpi_dp_ofnode_copy_str(node, dp, "setting")); + ut_asserteq(-EINVAL, + acpi_dp_ofnode_copy_str(node, dp, "missing-value")); + + ptr = acpigen_get_current(ctx); + ut_assertok(acpi_dp_write(ctx, dp)); + ut_asserteq(0x9d, acpigen_get_current(ctx) - ptr); + + ut_asserteq(STRING_PREFIX, ptr[0x2b]); + ut_asserteq_str("int-value", (char *)ptr + 0x2c); + ut_asserteq(WORD_PREFIX, ptr[0x36]); + ut_asserteq(1234, get_unaligned((u16 *)(ptr + 0x37))); + + ut_asserteq(STRING_PREFIX, ptr[0x3e]); + ut_asserteq_str("uint-value", (char *)ptr + 0x3f); + ut_asserteq(DWORD_PREFIX, ptr[0x4a]); + ut_asserteq(-1234, get_unaligned((u32 *)(ptr + 0x4b))); + + ut_asserteq(STRING_PREFIX, ptr[0x54]); + ut_asserteq_str("str-value", (char *)ptr + 0x55); + ut_asserteq(STRING_PREFIX, ptr[0x5f]); + ut_asserteq_str("test string", (char *)ptr + 0x60); + + ut_asserteq(STRING_PREFIX, ptr[0x71]); + ut_asserteq_str("int-values", (char *)ptr + 0x72); + ut_asserteq(WORD_PREFIX, ptr[0x7d]); + ut_asserteq(0x1937, get_unaligned((u16 *)(ptr + 0x7e))); + + ut_asserteq(STRING_PREFIX, ptr[0x85]); + ut_asserteq_str("setting", (char *)ptr + 0x86); + ut_asserteq(STRING_PREFIX, ptr[0x8e]); + ut_asserteq_str("sunrise ohoka", (char *)(ptr + 0x8f)); + + return 0; +} +DM_TEST(dm_test_acpi_dp_copy, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); diff --git a/roms/u-boot/test/dm/acpigen.c b/roms/u-boot/test/dm/acpigen.c new file mode 100644 index 000000000..3ec2743af --- /dev/null +++ b/roms/u-boot/test/dm/acpigen.c @@ -0,0 +1,1746 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Tests for ACPI code generation + * + * Copyright 2019 Google LLC + * Written by Simon Glass <sjg@chromium.org> + */ + +#include <common.h> +#include <dm.h> +#include <irq.h> +#include <malloc.h> +#include <uuid.h> +#include <acpi/acpigen.h> +#include <acpi/acpi_device.h> +#include <acpi/acpi_table.h> +#include <asm/gpio.h> +#include <asm/unaligned.h> +#include <dm/acpi.h> +#include <dm/test.h> +#include <dm/uclass-internal.h> +#include <test/ut.h> +#include "acpi.h" + +/* Maximum size of the ACPI context needed for most tests */ +#define ACPI_CONTEXT_SIZE 150 + +#define TEST_STRING "frogmore" +#define TEST_STRING2 "ranch" +#define TEST_STREAM2 "\xfa\xde" + +#define TEST_INT8 0x7d +#define TEST_INT16 0x2345 +#define TEST_INT32 0x12345678 +#define TEST_INT64 0x4567890123456 + +int acpi_test_alloc_context_size(struct acpi_ctx **ctxp, int size) +{ + struct acpi_ctx *ctx; + + *ctxp = NULL; + ctx = malloc(sizeof(*ctx)); + if (!ctx) + return -ENOMEM; + ctx->base = malloc(size); + if (!ctx->base) { + free(ctx); + return -ENOMEM; + } + ctx->ltop = 0; + ctx->current = ctx->base; + *ctxp = ctx; + + return 0; +} + +int acpi_test_get_length(u8 *ptr) +{ + if (!(*ptr & 0x80)) + return -EINVAL; + + return (*ptr & 0xf) | ptr[1] << 4 | ptr[2] << 12; +} + +static int alloc_context(struct acpi_ctx **ctxp) +{ + return acpi_test_alloc_context_size(ctxp, ACPI_CONTEXT_SIZE); +} + +static void free_context(struct acpi_ctx **ctxp) +{ + free((*ctxp)->base); + free(*ctxp); + *ctxp = NULL; +} + +/* Test emitting simple types and acpigen_get_current() */ +static int dm_test_acpi_emit_simple(struct unit_test_state *uts) +{ + struct acpi_ctx *ctx; + u8 *ptr; + + ut_assertok(alloc_context(&ctx)); + + ptr = acpigen_get_current(ctx); + acpigen_emit_byte(ctx, 0x23); + ut_asserteq(1, acpigen_get_current(ctx) - ptr); + ut_asserteq(0x23, *(u8 *)ptr); + + acpigen_emit_word(ctx, 0x1234); + ut_asserteq(3, acpigen_get_current(ctx) - ptr); + ut_asserteq(0x1234, get_unaligned((u16 *)(ptr + 1))); + + acpigen_emit_dword(ctx, 0x87654321); + ut_asserteq(7, acpigen_get_current(ctx) - ptr); + ut_asserteq(0x87654321, get_unaligned((u32 *)(ptr + 3))); + + free_context(&ctx); + + return 0; +} +DM_TEST(dm_test_acpi_emit_simple, 0); + +/* Test emitting a stream */ +static int dm_test_acpi_emit_stream(struct unit_test_state *uts) +{ + struct acpi_ctx *ctx; + u8 *ptr; + + ut_assertok(alloc_context(&ctx)); + + ptr = acpigen_get_current(ctx); + acpigen_emit_stream(ctx, TEST_STREAM2, 2); + ut_asserteq(2, acpigen_get_current(ctx) - ptr); + ut_asserteq((u8)TEST_STREAM2[0], ptr[0]); + ut_asserteq((u8)TEST_STREAM2[1], ptr[1]); + + free_context(&ctx); + + return 0; +} +DM_TEST(dm_test_acpi_emit_stream, 0); + +/* Test emitting a string */ +static int dm_test_acpi_emit_string(struct unit_test_state *uts) +{ + struct acpi_ctx *ctx; + u8 *ptr; + + ut_assertok(alloc_context(&ctx)); + + ptr = acpigen_get_current(ctx); + acpigen_emit_string(ctx, TEST_STRING); + ut_asserteq(sizeof(TEST_STRING), acpigen_get_current(ctx) - ptr); + ut_asserteq_str(TEST_STRING, (char *)ptr); + + free_context(&ctx); + + return 0; +} +DM_TEST(dm_test_acpi_emit_string, 0); + +/* Test emitting an interrupt descriptor */ +static int dm_test_acpi_interrupt(struct unit_test_state *uts) +{ + struct acpi_ctx *ctx; + struct udevice *dev; + struct irq irq; + u8 *ptr; + + ut_assertok(alloc_context(&ctx)); + + ptr = acpigen_get_current(ctx); + + ut_assertok(uclass_first_device_err(UCLASS_TEST_FDT, &dev)); + ut_assertok(irq_get_by_index(dev, 0, &irq)); + + /* See a-test, property interrupts-extended in the device tree */ + ut_asserteq(3, acpi_device_write_interrupt_irq(ctx, &irq)); + ut_asserteq(9, acpigen_get_current(ctx) - ptr); + ut_asserteq(ACPI_DESCRIPTOR_INTERRUPT, ptr[0]); + ut_asserteq(6, get_unaligned((u16 *)(ptr + 1))); + ut_asserteq(0x19, ptr[3]); + ut_asserteq(1, ptr[4]); + ut_asserteq(3, get_unaligned((u32 *)(ptr + 5))); + + free_context(&ctx); + + return 0; +} +DM_TEST(dm_test_acpi_interrupt, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); + +/* Test emitting a GPIO descriptor */ +static int dm_test_acpi_gpio(struct unit_test_state *uts) +{ + struct gpio_desc desc; + struct acpi_ctx *ctx; + struct udevice *dev; + u8 *ptr; + + ut_assertok(alloc_context(&ctx)); + + ptr = acpigen_get_current(ctx); + + ut_assertok(uclass_get_device(UCLASS_TEST_FDT, 0, &dev)); + ut_asserteq_str("a-test", dev->name); + ut_assertok(gpio_request_by_name(dev, "test-gpios", 1, &desc, 0)); + + /* This should write GPIO pin 4 (see device tree test.dts ) */ + ut_asserteq(4, acpi_device_write_gpio_desc(ctx, &desc)); + ut_asserteq(35, acpigen_get_current(ctx) - ptr); + ut_asserteq(ACPI_DESCRIPTOR_GPIO, ptr[0]); + ut_asserteq(32, get_unaligned((u16 *)(ptr + 1))); + ut_asserteq(ACPI_GPIO_REVISION_ID, ptr[3]); + ut_asserteq(ACPI_GPIO_TYPE_IO, ptr[4]); + ut_asserteq(1, get_unaligned((u16 *)(ptr + 5))); + ut_asserteq(9, get_unaligned((u16 *)(ptr + 7))); + ut_asserteq(ACPI_GPIO_PULL_UP, ptr[9]); + ut_asserteq(1234, get_unaligned((u16 *)(ptr + 10))); + ut_asserteq(0, get_unaligned((u16 *)(ptr + 12))); + ut_asserteq(23, get_unaligned((u16 *)(ptr + 14))); + ut_asserteq(0, ptr[16]); + ut_asserteq(25, get_unaligned((u16 *)(ptr + 17))); + ut_asserteq(35, get_unaligned((u16 *)(ptr + 19))); + ut_asserteq(0, get_unaligned((u16 *)(ptr + 21))); + + /* pin0 */ + ut_asserteq(4, get_unaligned((u16 *)(ptr + 23))); + + ut_asserteq_str("\\_SB.PINC", (char *)ptr + 25); + + free_context(&ctx); + + return 0; +} +DM_TEST(dm_test_acpi_gpio, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); + +/* Test emitting a GPIO descriptor with an interrupt */ +static int dm_test_acpi_gpio_irq(struct unit_test_state *uts) +{ + struct gpio_desc desc; + struct acpi_ctx *ctx; + struct udevice *dev; + u8 *ptr; + + ut_assertok(alloc_context(&ctx)); + + ptr = acpigen_get_current(ctx); + + ut_assertok(uclass_get_device(UCLASS_TEST_FDT, 0, &dev)); + ut_asserteq_str("a-test", dev->name); + ut_assertok(gpio_request_by_name(dev, "test2-gpios", 2, &desc, 0)); + + /* This should write GPIO pin 6 (see device tree test.dts ) */ + ut_asserteq(6, acpi_device_write_gpio_desc(ctx, &desc)); + ut_asserteq(35, acpigen_get_current(ctx) - ptr); + ut_asserteq(ACPI_DESCRIPTOR_GPIO, ptr[0]); + ut_asserteq(32, get_unaligned((u16 *)(ptr + 1))); + ut_asserteq(ACPI_GPIO_REVISION_ID, ptr[3]); + ut_asserteq(ACPI_GPIO_TYPE_INTERRUPT, ptr[4]); + ut_asserteq(1, get_unaligned((u16 *)(ptr + 5))); + ut_asserteq(29, get_unaligned((u16 *)(ptr + 7))); + ut_asserteq(ACPI_GPIO_PULL_DOWN, ptr[9]); + ut_asserteq(0, get_unaligned((u16 *)(ptr + 10))); + ut_asserteq(4321, get_unaligned((u16 *)(ptr + 12))); + ut_asserteq(23, get_unaligned((u16 *)(ptr + 14))); + ut_asserteq(0, ptr[16]); + ut_asserteq(25, get_unaligned((u16 *)(ptr + 17))); + ut_asserteq(35, get_unaligned((u16 *)(ptr + 19))); + ut_asserteq(0, get_unaligned((u16 *)(ptr + 21))); + + /* pin0 */ + ut_asserteq(6, get_unaligned((u16 *)(ptr + 23))); + + ut_asserteq_str("\\_SB.PINC", (char *)ptr + 25); + + free_context(&ctx); + + return 0; +} +DM_TEST(dm_test_acpi_gpio_irq, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); + +/* Test emitting either a GPIO or interrupt descriptor */ +static int dm_test_acpi_interrupt_or_gpio(struct unit_test_state *uts) +{ + struct acpi_ctx *ctx; + struct udevice *dev; + u8 *ptr; + + ut_assertok(alloc_context(&ctx)); + + ptr = acpigen_get_current(ctx); + + /* This should produce an interrupt, even though it also has a GPIO */ + ut_assertok(uclass_get_device(UCLASS_TEST_FDT, 0, &dev)); + ut_asserteq_str("a-test", dev->name); + ut_asserteq(3, acpi_device_write_interrupt_or_gpio(ctx, dev, + "test2-gpios")); + ut_asserteq(ACPI_DESCRIPTOR_INTERRUPT, ptr[0]); + + /* This has no interrupt so should produce a GPIO */ + ptr = ctx->current; + ut_assertok(uclass_find_first_device(UCLASS_PANEL_BACKLIGHT, &dev)); + ut_asserteq(1, acpi_device_write_interrupt_or_gpio(ctx, dev, + "enable-gpios")); + ut_asserteq(ACPI_DESCRIPTOR_GPIO, ptr[0]); + + /* This one has neither */ + ptr = acpigen_get_current(ctx); + ut_assertok(uclass_get_device_by_seq(UCLASS_TEST_FDT, 3, &dev)); + ut_asserteq_str("b-test", dev->name); + ut_asserteq(-ENOENT, + acpi_device_write_interrupt_or_gpio(ctx, dev, + "enable-gpios")); + + free_context(&ctx); + + return 0; +} +DM_TEST(dm_test_acpi_interrupt_or_gpio, + UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); + +/* Test emitting an I2C descriptor */ +static int dm_test_acpi_i2c(struct unit_test_state *uts) +{ + struct acpi_ctx *ctx; + struct udevice *dev; + u8 *ptr; + + ut_assertok(alloc_context(&ctx)); + + ptr = acpigen_get_current(ctx); + + ut_assertok(uclass_get_device(UCLASS_RTC, 0, &dev)); + ut_asserteq(0x43, acpi_device_write_i2c_dev(ctx, dev)); + ut_asserteq(28, acpigen_get_current(ctx) - ptr); + ut_asserteq(ACPI_DESCRIPTOR_SERIAL_BUS, ptr[0]); + ut_asserteq(25, get_unaligned((u16 *)(ptr + 1))); + ut_asserteq(ACPI_I2C_SERIAL_BUS_REVISION_ID, ptr[3]); + ut_asserteq(0, ptr[4]); + ut_asserteq(ACPI_SERIAL_BUS_TYPE_I2C, ptr[5]); + ut_asserteq(0, get_unaligned((u16 *)(ptr + 7))); + ut_asserteq(ACPI_I2C_TYPE_SPECIFIC_REVISION_ID, ptr[9]); + ut_asserteq(6, get_unaligned((u16 *)(ptr + 10))); + ut_asserteq(100000, get_unaligned((u32 *)(ptr + 12))); + ut_asserteq(0x43, get_unaligned((u16 *)(ptr + 16))); + ut_asserteq_str("\\_SB.I2C0", (char *)ptr + 18); + + free_context(&ctx); + + return 0; +} +DM_TEST(dm_test_acpi_i2c, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); + +/* Test emitting a SPI descriptor */ +static int dm_test_acpi_spi(struct unit_test_state *uts) +{ + struct acpi_ctx *ctx; + struct udevice *dev; + u8 *ptr; + + ut_assertok(alloc_context(&ctx)); + + ptr = acpigen_get_current(ctx); + + ut_assertok(uclass_first_device_err(UCLASS_SPI_FLASH, &dev)); + ut_assertok(acpi_device_write_spi_dev(ctx, dev)); + ut_asserteq(31, acpigen_get_current(ctx) - ptr); + ut_asserteq(ACPI_DESCRIPTOR_SERIAL_BUS, ptr[0]); + ut_asserteq(28, get_unaligned((u16 *)(ptr + 1))); + ut_asserteq(ACPI_SPI_SERIAL_BUS_REVISION_ID, ptr[3]); + ut_asserteq(0, ptr[4]); + ut_asserteq(ACPI_SERIAL_BUS_TYPE_SPI, ptr[5]); + ut_asserteq(2, ptr[6]); + ut_asserteq(0, get_unaligned((u16 *)(ptr + 7))); + ut_asserteq(ACPI_SPI_TYPE_SPECIFIC_REVISION_ID, ptr[9]); + ut_asserteq(9, get_unaligned((u16 *)(ptr + 10))); + ut_asserteq(40000000, get_unaligned((u32 *)(ptr + 12))); + ut_asserteq(8, ptr[16]); + ut_asserteq(0, ptr[17]); + ut_asserteq(0, ptr[18]); + ut_asserteq(0, get_unaligned((u16 *)(ptr + 19))); + ut_asserteq_str("\\_SB.SPI0", (char *)ptr + 21); + + free_context(&ctx); + + return 0; +} +DM_TEST(dm_test_acpi_spi, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); + +/* Test emitting a length */ +static int dm_test_acpi_len(struct unit_test_state *uts) +{ + const int size = 0xc0000; + struct acpi_ctx *ctx; + u8 *ptr; + int i; + + ut_assertok(acpi_test_alloc_context_size(&ctx, size)); + + ptr = acpigen_get_current(ctx); + + /* Write a byte and a 3-byte length */ + acpigen_write_len_f(ctx); + acpigen_emit_byte(ctx, 0x23); + acpigen_pop_len(ctx); + ut_asserteq(1 + 3, acpi_test_get_length(ptr)); + + /* Write 200 bytes so we need two length bytes */ + ptr = ctx->current; + acpigen_write_len_f(ctx); + for (i = 0; i < 200; i++) + acpigen_emit_byte(ctx, 0x23); + acpigen_pop_len(ctx); + ut_asserteq(200 + 3, acpi_test_get_length(ptr)); + + /* Write 40KB so we need three length bytes */ + ptr = ctx->current; + acpigen_write_len_f(ctx); + for (i = 0; i < 40000; i++) + acpigen_emit_byte(ctx, 0x23); + acpigen_pop_len(ctx); + ut_asserteq(40000 + 3, acpi_test_get_length(ptr)); + + free_context(&ctx); + + return 0; +} +DM_TEST(dm_test_acpi_len, 0); + +/* Test writing a package */ +static int dm_test_acpi_package(struct unit_test_state *uts) +{ + struct acpi_ctx *ctx; + char *num_elements; + u8 *ptr; + + ut_assertok(alloc_context(&ctx)); + + ptr = acpigen_get_current(ctx); + + num_elements = acpigen_write_package(ctx, 3); + ut_asserteq_ptr(num_elements, ptr + 4); + + /* For ease of testing, just emit a byte, not valid package contents */ + acpigen_emit_byte(ctx, 0x23); + acpigen_pop_len(ctx); + ut_asserteq(PACKAGE_OP, ptr[0]); + ut_asserteq(5, acpi_test_get_length(ptr + 1)); + ut_asserteq(3, ptr[4]); + + free_context(&ctx); + + return 0; +} +DM_TEST(dm_test_acpi_package, 0); + +/* Test writing an integer */ +static int dm_test_acpi_integer(struct unit_test_state *uts) +{ + struct acpi_ctx *ctx; + u8 *ptr; + + ut_assertok(alloc_context(&ctx)); + + ptr = acpigen_get_current(ctx); + + acpigen_write_integer(ctx, 0); + acpigen_write_integer(ctx, 1); + acpigen_write_integer(ctx, TEST_INT8); + acpigen_write_integer(ctx, TEST_INT16); + acpigen_write_integer(ctx, TEST_INT32); + acpigen_write_integer(ctx, TEST_INT64); + + ut_asserteq(6 + 1 + 2 + 4 + 8, acpigen_get_current(ctx) - ptr); + + ut_asserteq(ZERO_OP, ptr[0]); + + ut_asserteq(ONE_OP, ptr[1]); + + ut_asserteq(BYTE_PREFIX, ptr[2]); + ut_asserteq(TEST_INT8, ptr[3]); + + ut_asserteq(WORD_PREFIX, ptr[4]); + ut_asserteq(TEST_INT16, get_unaligned((u16 *)(ptr + 5))); + + ut_asserteq(DWORD_PREFIX, ptr[7]); + ut_asserteq(TEST_INT32, get_unaligned((u32 *)(ptr + 8))); + + ut_asserteq(QWORD_PREFIX, ptr[12]); + ut_asserteq_64(TEST_INT64, get_unaligned((u64 *)(ptr + 13))); + + free_context(&ctx); + + return 0; +} +DM_TEST(dm_test_acpi_integer, 0); + +/* Test writing a string */ +static int dm_test_acpi_string(struct unit_test_state *uts) +{ + struct acpi_ctx *ctx; + u8 *ptr; + + ut_assertok(alloc_context(&ctx)); + + ptr = acpigen_get_current(ctx); + + acpigen_write_string(ctx, TEST_STRING); + acpigen_write_string(ctx, TEST_STRING2); + + ut_asserteq(2 + sizeof(TEST_STRING) + sizeof(TEST_STRING2), + acpigen_get_current(ctx) - ptr); + ut_asserteq(STRING_PREFIX, ptr[0]); + ut_asserteq_str(TEST_STRING, (char *)ptr + 1); + ptr += 1 + sizeof(TEST_STRING); + ut_asserteq(STRING_PREFIX, ptr[0]); + ut_asserteq_str(TEST_STRING2, (char *)ptr + 1); + + free_context(&ctx); + + return 0; +} +DM_TEST(dm_test_acpi_string, 0); + +/* Test writing a name */ +static int dm_test_acpi_name(struct unit_test_state *uts) +{ + struct acpi_ctx *ctx; + u8 *ptr; + + ut_assertok(alloc_context(&ctx)); + + ptr = acpigen_get_current(ctx); + + /* + * The names here are made up for testing the various cases. The + * grammar is in the ACPI spec 6.3 section 19.2.2 + */ + acpigen_write_name(ctx, "\\_SB"); + acpigen_write_name(ctx, "\\_SB.I2C0"); + acpigen_write_name(ctx, "\\_SB.I2C0.TPM2"); + acpigen_write_name(ctx, "\\_SB.I2C0.TPM2.LONG"); + acpigen_write_name(ctx, "^^^^SPI0.FLAS"); + acpigen_write_name(ctx, "NN"); + acpigen_write_name(ctx, "^AB.CD.D.EFG"); + acpigen_write_name(ctx, "^^^^"); + acpigen_write_name(ctx, "\\"); + acpigen_write_name(ctx, "\\ABCD"); + + ut_asserteq(107, acpigen_get_current(ctx) - ptr); + ut_asserteq(NAME_OP, ptr[0]); + ut_asserteq_strn("\\_SB_", (char *)ptr + 1); + ptr += 6; + + ut_asserteq(NAME_OP, ptr[0]); + ut_asserteq('\\', ptr[1]); + ut_asserteq(DUAL_NAME_PREFIX, ptr[2]); + ut_asserteq_strn("_SB_I2C0", (char *)ptr + 3); + ptr += 11; + + ut_asserteq(NAME_OP, ptr[0]); + ut_asserteq('\\', ptr[1]); + ut_asserteq(MULTI_NAME_PREFIX, ptr[2]); + ut_asserteq(3, ptr[3]); + ut_asserteq_strn("_SB_I2C0TPM2", (char *)ptr + 4); + ptr += 16; + + ut_asserteq(NAME_OP, ptr[0]); + ut_asserteq('\\', ptr[1]); + ut_asserteq(MULTI_NAME_PREFIX, ptr[2]); + ut_asserteq(4, ptr[3]); + ut_asserteq_strn("_SB_I2C0TPM2LONG", (char *)ptr + 4); + ptr += 20; + + ut_asserteq(NAME_OP, ptr[0]); + ut_asserteq('^', ptr[1]); + ut_asserteq('^', ptr[2]); + ut_asserteq('^', ptr[3]); + ut_asserteq('^', ptr[4]); + ut_asserteq(DUAL_NAME_PREFIX, ptr[5]); + ut_asserteq_strn("SPI0FLAS", (char *)ptr + 6); + ptr += 14; + + ut_asserteq(NAME_OP, ptr[0]); + ut_asserteq_strn("NN__", (char *)ptr + 1); + ptr += 5; + + ut_asserteq(NAME_OP, ptr[0]); + ut_asserteq('^', ptr[1]); + ut_asserteq(MULTI_NAME_PREFIX, ptr[2]); + ut_asserteq(4, ptr[3]); + ut_asserteq_strn("AB__CD__D___EFG_", (char *)ptr + 4); + ptr += 20; + + ut_asserteq(NAME_OP, ptr[0]); + ut_asserteq('^', ptr[1]); + ut_asserteq('^', ptr[2]); + ut_asserteq('^', ptr[3]); + ut_asserteq('^', ptr[4]); + ut_asserteq(ZERO_OP, ptr[5]); + ptr += 6; + + ut_asserteq(NAME_OP, ptr[0]); + ut_asserteq('\\', ptr[1]); + ut_asserteq(ZERO_OP, ptr[2]); + ptr += 3; + + ut_asserteq(NAME_OP, ptr[0]); + ut_asserteq_strn("\\ABCD", (char *)ptr + 1); + ptr += 5; + + free_context(&ctx); + + return 0; +} +DM_TEST(dm_test_acpi_name, 0); + +/* Test writing a UUID */ +static int dm_test_acpi_uuid(struct unit_test_state *uts) +{ + struct acpi_ctx *ctx; + u8 *ptr; + + ut_assertok(alloc_context(&ctx)); + + ptr = acpigen_get_current(ctx); + + ut_assertok(acpigen_write_uuid(ctx, + "dbb8e3e6-5886-4ba6-8795-1319f52a966b")); + ut_asserteq(23, acpigen_get_current(ctx) - ptr); + ut_asserteq(BUFFER_OP, ptr[0]); + ut_asserteq(22, acpi_test_get_length(ptr + 1)); + ut_asserteq(0xdbb8e3e6, get_unaligned((u32 *)(ptr + 7))); + ut_asserteq(0x5886, get_unaligned((u16 *)(ptr + 11))); + ut_asserteq(0x4ba6, get_unaligned((u16 *)(ptr + 13))); + ut_asserteq(0x9587, get_unaligned((u16 *)(ptr + 15))); + ut_asserteq(0x2af51913, get_unaligned((u32 *)(ptr + 17))); + ut_asserteq(0x6b96, get_unaligned((u16 *)(ptr + 21))); + + /* Try a bad UUID */ + ut_asserteq(-EINVAL, + acpigen_write_uuid(ctx, + "dbb8e3e6-5886-4ba6x8795-1319f52a966b")); + + free_context(&ctx); + + return 0; +} +DM_TEST(dm_test_acpi_uuid, 0); + +/* Test writing misc ACPI codes */ +static int dm_test_acpi_misc(struct unit_test_state *uts) +{ + struct acpi_ctx *ctx; + const int flags = 3; + const int nargs = 4; + u8 *ptr; + + ut_assertok(alloc_context(&ctx)); + + ptr = acpigen_get_current(ctx); + acpigen_write_sleep(ctx, TEST_INT64); + ut_asserteq_64(TEST_INT64, get_unaligned((u64 *)(ptr + 3))); + ptr += 11; + + acpigen_write_store(ctx); + ut_asserteq(STORE_OP, *ptr); + ptr++; + + acpigen_write_debug_string(ctx, TEST_STRING); + ut_asserteq_str(TEST_STRING, (char *)ptr + 2); + ptr += 2 + sizeof(TEST_STRING); + ut_asserteq(EXT_OP_PREFIX, ptr[0]); + ut_asserteq(DEBUG_OP, ptr[1]); + ptr += 2; + + acpigen_write_sta(ctx, flags); + ut_asserteq(METHOD_OP, ptr[0]); + ut_asserteq(11, acpi_test_get_length(ptr + 1)); + ut_asserteq_strn("_STA", (char *)ptr + 4); + ut_asserteq(0, ptr[8]); + ut_asserteq(RETURN_OP, ptr[9]); + ut_asserteq(BYTE_PREFIX, ptr[10]); + ut_asserteq(flags, ptr[11]); + ptr += 12; + + acpigen_write_sleep(ctx, TEST_INT16); + ut_asserteq(SLEEP_OP, ptr[1]); + ut_asserteq(TEST_INT16, get_unaligned((u16 *)(ptr + 3))); + ptr += 5; + + acpigen_write_method_serialized(ctx, "FRED", nargs); + ut_asserteq(METHOD_OP, ptr[0]); + ut_asserteq_strn("FRED", (char *)ptr + 4); + ut_asserteq(1 << 3 | nargs, ptr[8]); + ut_asserteq(1, ctx->ltop); /* method is unfinished */ + + ptr += 9; + acpigen_write_or(ctx, LOCAL0_OP, LOCAL1_OP, LOCAL2_OP); + acpigen_write_and(ctx, LOCAL3_OP, LOCAL4_OP, LOCAL5_OP); + acpigen_write_not(ctx, LOCAL6_OP, LOCAL7_OP); + ut_asserteq(OR_OP, ptr[0]); + ut_asserteq(LOCAL0_OP, ptr[1]); + ut_asserteq(LOCAL1_OP, ptr[2]); + ut_asserteq(LOCAL2_OP, ptr[3]); + + ptr += 4; + ut_asserteq(AND_OP, ptr[0]); + ut_asserteq(LOCAL3_OP, ptr[1]); + ut_asserteq(LOCAL4_OP, ptr[2]); + ut_asserteq(LOCAL5_OP, ptr[3]); + + ptr += 4; + ut_asserteq(NOT_OP, ptr[0]); + ut_asserteq(LOCAL6_OP, ptr[1]); + ut_asserteq(LOCAL7_OP, ptr[2]); + ptr += 3; + ut_asserteq_ptr(ptr, ctx->current); + + free_context(&ctx); + + return 0; +} +DM_TEST(dm_test_acpi_misc, 0); + +/* Test writing an ACPI power resource */ +static int dm_test_acpi_power_res(struct unit_test_state *uts) +{ + const char *const states[] = { "_PR0", "_PR3" }; + const char *name = "PRIC"; + const int level = 3; + const int order = 2; + struct acpi_ctx *ctx; + u8 *ptr; + + ut_assertok(alloc_context(&ctx)); + + ptr = acpigen_get_current(ctx); + + /* PowerResource (PRIC, 0, 0) */ + acpigen_write_power_res(ctx, name, level, order, states, + ARRAY_SIZE(states)); + ut_asserteq(0x28, acpigen_get_current(ctx) - ptr); + ut_asserteq(NAME_OP, ptr[0]); + ut_asserteq_strn(states[0], (char *)ptr + 1); + ut_asserteq(8, acpi_test_get_length(ptr + 6)); + ut_asserteq_strn(name, (char *)ptr + 0xa); + + ut_asserteq_strn(states[1], (char *)ptr + 0xf); + ut_asserteq(8, acpi_test_get_length(ptr + 0x14)); + ut_asserteq_strn(name, (char *)ptr + 0x18); + + ut_asserteq(POWER_RES_OP, ptr[0x1d]); + ut_asserteq_strn(name, (char *)ptr + 0x21); + ut_asserteq(level, ptr[0x25]); + ut_asserteq(order, get_unaligned((u16 *)(ptr + 0x26))); + + /* The length is not set - caller must use acpigen_pop_len() */ + ut_asserteq(1, ctx->ltop); + + free_context(&ctx); + + return 0; +} +DM_TEST(dm_test_acpi_power_res, 0); + +/* Test writing ACPI code to toggle a GPIO */ +static int dm_test_acpi_gpio_toggle(struct unit_test_state *uts) +{ + const uint addr = 0x80012; + const int txbit = BIT(2); + struct gpio_desc desc; + struct acpi_gpio gpio; + struct acpi_ctx *ctx; + struct udevice *dev; + u8 *ptr; + + ut_assertok(alloc_context(&ctx)); + + ut_assertok(uclass_get_device(UCLASS_TEST_FDT, 0, &dev)); + ut_asserteq_str("a-test", dev->name); + ut_assertok(gpio_request_by_name(dev, "test2-gpios", 2, &desc, 0)); + ut_assertok(gpio_get_acpi(&desc, &gpio)); + + /* Spot-check the results - see sb_gpio_get_acpi() */ + ptr = acpigen_get_current(ctx); + acpigen_set_enable_tx_gpio(ctx, txbit, "\\_SB.GPC0", "\\_SB.SPC0", + &gpio, true); + acpigen_set_enable_tx_gpio(ctx, txbit, "\\_SB.GPC0", "\\_SB.SPC0", + &gpio, false); + + /* Since this GPIO is active low, we expect it to be cleared here */ + ut_asserteq(STORE_OP, *ptr); + ut_asserteq_strn("_SB_GPC0", (char *)ptr + 3); + ut_asserteq(addr + desc.offset, get_unaligned((u32 *)(ptr + 0xc))); + ut_asserteq(LOCAL5_OP, ptr[0x10]); + + ut_asserteq(STORE_OP, ptr[0x11]); + ut_asserteq(BYTE_PREFIX, ptr[0x12]); + ut_asserteq(txbit, ptr[0x13]); + ut_asserteq(LOCAL0_OP, ptr[0x14]); + + ut_asserteq(NOT_OP, ptr[0x15]); + ut_asserteq(LOCAL0_OP, ptr[0x16]); + ut_asserteq(LOCAL6_OP, ptr[0x17]); + ut_asserteq(AND_OP, ptr[0x18]); + ut_asserteq_strn("_SB_SPC0", (char *)ptr + 0x1e); + ut_asserteq(addr + desc.offset, get_unaligned((u32 *)(ptr + 0x27))); + ut_asserteq(LOCAL5_OP, ptr[0x2b]); + + /* Now the second one, which should be set */ + ut_asserteq_strn("_SB_GPC0", (char *)ptr + 0x2f); + ut_asserteq(addr + desc.offset, get_unaligned((u32 *)(ptr + 0x38))); + ut_asserteq(LOCAL5_OP, ptr[0x3c]); + + ut_asserteq(STORE_OP, ptr[0x3d]); + + ut_asserteq(OR_OP, ptr[0x41]); + ut_asserteq(LOCAL0_OP, ptr[0x43]); + ut_asserteq_strn("_SB_SPC0", (char *)ptr + 0x47); + ut_asserteq(addr + desc.offset, get_unaligned((u32 *)(ptr + 0x50))); + ut_asserteq(LOCAL5_OP, ptr[0x54]); + ut_asserteq(0x55, acpigen_get_current(ctx) - ptr); + + free_context(&ctx); + + return 0; +} +DM_TEST(dm_test_acpi_gpio_toggle, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); + +/* Test writing ACPI code to output power-sequence info */ +static int dm_test_acpi_power_seq(struct unit_test_state *uts) +{ + struct gpio_desc reset, enable, stop; + const uint addr = 0xc00dc, addr_act_low = 0x80012; + const int txbit = BIT(2); + struct acpi_ctx *ctx; + struct udevice *dev; + u8 *ptr; + + ut_assertok(acpi_test_alloc_context_size(&ctx, 400)); + + ut_assertok(uclass_get_device(UCLASS_TEST_FDT, 0, &dev)); + ut_asserteq_str("a-test", dev->name); + ut_assertok(gpio_request_by_name(dev, "test2-gpios", 0, &reset, 0)); + ut_assertok(gpio_request_by_name(dev, "test2-gpios", 1, &enable, 0)); + ut_assertok(gpio_request_by_name(dev, "test2-gpios", 2, &stop, 0)); + ptr = acpigen_get_current(ctx); + + ut_assertok(acpi_device_add_power_res(ctx, txbit, "\\_SB.GPC0", + "\\_SB.SPC0", &reset, 2, 3, + &enable, 4, 5, &stop, 6, 7)); + ut_asserteq(0x186, acpigen_get_current(ctx) - ptr); + ut_asserteq_strn("PRIC", (char *)ptr + 0x18); + + /* First the 'ON' sequence - spot check */ + ut_asserteq_strn("_ON_", (char *)ptr + 0x38); + + /* reset set */ + ut_asserteq(addr + reset.offset, get_unaligned((u32 *)(ptr + 0x49))); + ut_asserteq(OR_OP, ptr[0x52]); + + /* enable set */ + ut_asserteq(addr + enable.offset, get_unaligned((u32 *)(ptr + 0x72))); + ut_asserteq(OR_OP, ptr[0x7b]); + + /* reset clear */ + ut_asserteq(addr + reset.offset, get_unaligned((u32 *)(ptr + 0x9f))); + ut_asserteq(NOT_OP, ptr[0xa8]); + + /* stop set (disable, active low) */ + ut_asserteq(addr_act_low + stop.offset, + get_unaligned((u32 *)(ptr + 0xcf))); + ut_asserteq(OR_OP, ptr[0xd8]); + + /* Now the 'OFF' sequence */ + ut_asserteq_strn("_OFF", (char *)ptr + 0xf4); + + /* stop clear (enable, active low) */ + ut_asserteq(addr_act_low + stop.offset, + get_unaligned((u32 *)(ptr + 0x105))); + ut_asserteq(NOT_OP, ptr[0x10e]); + + /* reset clear */ + ut_asserteq(addr + reset.offset, get_unaligned((u32 *)(ptr + 0x135))); + ut_asserteq(OR_OP, ptr[0x13e]); + + /* enable clear */ + ut_asserteq(addr + enable.offset, get_unaligned((u32 *)(ptr + 0x162))); + ut_asserteq(NOT_OP, ptr[0x16b]); + + free_context(&ctx); + + return 0; +} +DM_TEST(dm_test_acpi_power_seq, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); + +/* Test writing values */ +static int dm_test_acpi_write_values(struct unit_test_state *uts) +{ + struct acpi_ctx *ctx; + u8 *ptr; + + ut_assertok(alloc_context(&ctx)); + ptr = acpigen_get_current(ctx); + + acpigen_write_zero(ctx); + acpigen_write_one(ctx); + acpigen_write_byte(ctx, TEST_INT8); + acpigen_write_word(ctx, TEST_INT16); + acpigen_write_dword(ctx, TEST_INT32); + acpigen_write_qword(ctx, TEST_INT64); + + ut_asserteq(ZERO_OP, *ptr++); + + ut_asserteq(ONE_OP, *ptr++); + + ut_asserteq(BYTE_PREFIX, *ptr++); + ut_asserteq(TEST_INT8, *ptr++); + + ut_asserteq(WORD_PREFIX, *ptr++); + ut_asserteq(TEST_INT16, get_unaligned((u16 *)ptr)); + ptr += 2; + + ut_asserteq(DWORD_PREFIX, *ptr++); + ut_asserteq(TEST_INT32, get_unaligned((u32 *)ptr)); + ptr += 4; + + ut_asserteq(QWORD_PREFIX, *ptr++); + ut_asserteq_64(TEST_INT64, get_unaligned((u64 *)ptr)); + ptr += 8; + + ut_asserteq_ptr(ptr, ctx->current); + + free_context(&ctx); + + return 0; +} +DM_TEST(dm_test_acpi_write_values, 0); + +/* Test writing a scope */ +static int dm_test_acpi_scope(struct unit_test_state *uts) +{ + char buf[ACPI_PATH_MAX]; + struct acpi_ctx *ctx; + struct udevice *dev; + u8 *ptr; + + ut_assertok(alloc_context(&ctx)); + ptr = acpigen_get_current(ctx); + + ut_assertok(uclass_first_device_err(UCLASS_TEST_ACPI, &dev)); + ut_assertok(acpi_device_path(dev, buf, sizeof(buf))); + acpigen_write_scope(ctx, buf); + acpigen_pop_len(ctx); + + ut_asserteq(SCOPE_OP, *ptr++); + ut_asserteq(13, acpi_test_get_length(ptr)); + ptr += 3; + ut_asserteq(ROOT_PREFIX, *ptr++); + ut_asserteq(DUAL_NAME_PREFIX, *ptr++); + ut_asserteq_strn("_SB_" ACPI_TEST_DEV_NAME, (char *)ptr); + ptr += 8; + ut_asserteq_ptr(ptr, ctx->current); + + free_context(&ctx); + + return 0; +} +DM_TEST(dm_test_acpi_scope, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); + +/* Test writing a resource template */ +static int dm_test_acpi_resource_template(struct unit_test_state *uts) +{ + struct acpi_gen_regaddr addr; + struct acpi_ctx *ctx; + u8 *ptr; + + ut_assertok(alloc_context(&ctx)); + ptr = acpigen_get_current(ctx); + + addr.space_id = ACPI_ADDRESS_SPACE_EC; + addr.bit_width = 32; + addr.bit_offset = 8; + addr.access_size = ACPI_ACCESS_SIZE_DWORD_ACCESS; + addr.addrl = TEST_INT64 & 0xffffffff; + addr.addrh = TEST_INT64 >> 32; + acpigen_write_register_resource(ctx, &addr); + + ut_asserteq(BUFFER_OP, *ptr++); + ut_asserteq(0x17, acpi_test_get_length(ptr)); + ptr += 3; + ut_asserteq(WORD_PREFIX, *ptr++); + ut_asserteq(0x11, get_unaligned((u16 *)ptr)); + ptr += 2; + ut_asserteq(ACPI_DESCRIPTOR_REGISTER, *ptr++); + ut_asserteq(0xc, *ptr++); + ut_asserteq(0, *ptr++); + ut_asserteq(ACPI_ADDRESS_SPACE_EC, *ptr++); + ut_asserteq(32, *ptr++); + ut_asserteq(8, *ptr++); + ut_asserteq(ACPI_ACCESS_SIZE_DWORD_ACCESS, *ptr++); + ut_asserteq(TEST_INT64 & 0xffffffff, get_unaligned((u32 *)ptr)); + ptr += 4; + ut_asserteq(TEST_INT64 >> 32, get_unaligned((u32 *)ptr)); + ptr += 4; + ut_asserteq(ACPI_END_TAG, *ptr++); + ut_asserteq(0x00, *ptr++); + ut_asserteq_ptr(ptr, ctx->current); + + free_context(&ctx); + + return 0; +} +DM_TEST(dm_test_acpi_resource_template, 0); + +/* Test writing a device */ +static int dm_test_acpi_device(struct unit_test_state *uts) +{ + struct acpi_ctx *ctx; + u8 *ptr; + + ut_assertok(alloc_context(&ctx)); + ptr = acpigen_get_current(ctx); + + acpigen_write_device(ctx, "\\_SB." ACPI_TEST_DEV_NAME); + acpigen_pop_len(ctx); + + ut_asserteq(EXT_OP_PREFIX, *ptr++); + ut_asserteq(DEVICE_OP, *ptr++); + ut_asserteq(0xd, acpi_test_get_length(ptr)); + ptr += 3; + ut_asserteq(ROOT_PREFIX, *ptr++); + ut_asserteq(DUAL_NAME_PREFIX, *ptr++); + ptr += 8; + ut_asserteq_ptr(ptr, ctx->current); + + free_context(&ctx); + + return 0; +} +DM_TEST(dm_test_acpi_device, 0); + +/* Test writing named values */ +static int dm_test_acpi_write_name(struct unit_test_state *uts) +{ + const char *name = "\\_SB." ACPI_TEST_DEV_NAME; + struct acpi_ctx *ctx; + u8 *ptr; + + ut_assertok(alloc_context(&ctx)); + ptr = acpigen_get_current(ctx); + + acpigen_write_name_zero(ctx, name); + acpigen_write_name_one(ctx, name); + acpigen_write_name_byte(ctx, name, TEST_INT8); + acpigen_write_name_word(ctx, name, TEST_INT16); + acpigen_write_name_dword(ctx, name, TEST_INT32); + acpigen_write_name_qword(ctx, name, TEST_INT64); + acpigen_write_name_integer(ctx, name, TEST_INT64 + 1); + acpigen_write_name_string(ctx, name, "baldrick"); + acpigen_write_name_string(ctx, name, NULL); + + ut_asserteq(NAME_OP, *ptr++); + ut_asserteq_strn("\\._SB_ABCD", (char *)ptr); + ptr += 10; + ut_asserteq(ZERO_OP, *ptr++); + + ut_asserteq(NAME_OP, *ptr++); + ptr += 10; + ut_asserteq(ONE_OP, *ptr++); + + ut_asserteq(NAME_OP, *ptr++); + ptr += 10; + ut_asserteq(BYTE_PREFIX, *ptr++); + ut_asserteq(TEST_INT8, *ptr++); + + ut_asserteq(NAME_OP, *ptr++); + ptr += 10; + ut_asserteq(WORD_PREFIX, *ptr++); + ut_asserteq(TEST_INT16, get_unaligned((u16 *)ptr)); + ptr += 2; + + ut_asserteq(NAME_OP, *ptr++); + ptr += 10; + ut_asserteq(DWORD_PREFIX, *ptr++); + ut_asserteq(TEST_INT32, get_unaligned((u32 *)ptr)); + ptr += 4; + + ut_asserteq(NAME_OP, *ptr++); + ptr += 10; + ut_asserteq(QWORD_PREFIX, *ptr++); + ut_asserteq_64(TEST_INT64, get_unaligned((u64 *)ptr)); + ptr += 8; + + ut_asserteq(NAME_OP, *ptr++); + ptr += 10; + ut_asserteq(QWORD_PREFIX, *ptr++); + ut_asserteq_64(TEST_INT64 + 1, get_unaligned((u64 *)ptr)); + ptr += 8; + + ut_asserteq(NAME_OP, *ptr++); + ptr += 10; + ut_asserteq(STRING_PREFIX, *ptr++); + ut_asserteq_str("baldrick", (char *)ptr) + ptr += 9; + + ut_asserteq(NAME_OP, *ptr++); + ptr += 10; + ut_asserteq(STRING_PREFIX, *ptr++); + ut_asserteq('\0', *ptr++); + + ut_asserteq_ptr(ptr, ctx->current); + + free_context(&ctx); + + return 0; +} +DM_TEST(dm_test_acpi_write_name, 0); + +/* Test emitting a _PRW component */ +static int dm_test_acpi_write_prw(struct unit_test_state *uts) +{ + struct acpi_ctx *ctx; + u8 *ptr; + + ut_assertok(alloc_context(&ctx)); + + ptr = acpigen_get_current(ctx); + acpigen_write_prw(ctx, 5, 3); + ut_asserteq(NAME_OP, *ptr++); + + ut_asserteq_strn("_PRW", (char *)ptr); + ptr += 4; + ut_asserteq(PACKAGE_OP, *ptr++); + ut_asserteq(8, acpi_test_get_length(ptr)); + ptr += 3; + ut_asserteq(2, *ptr++); + ut_asserteq(BYTE_PREFIX, *ptr++); + ut_asserteq(5, *ptr++); + ut_asserteq(BYTE_PREFIX, *ptr++); + ut_asserteq(3, *ptr++); + ut_asserteq_ptr(ptr, ctx->current); + + free_context(&ctx); + + return 0; +} +DM_TEST(dm_test_acpi_write_prw, 0); + +/* Test emitting writing conditionals */ +static int dm_test_acpi_write_cond(struct unit_test_state *uts) +{ + struct acpi_ctx *ctx; + u8 *ptr; + + ut_assertok(alloc_context(&ctx)); + + ptr = acpigen_get_current(ctx); + acpigen_write_if(ctx); + acpigen_pop_len(ctx); + ut_asserteq(IF_OP, *ptr++); + ut_asserteq(3, acpi_test_get_length(ptr)); + ptr += 3; + + acpigen_write_else(ctx); + acpigen_pop_len(ctx); + ut_asserteq(ELSE_OP, *ptr++); + ut_asserteq(3, acpi_test_get_length(ptr)); + ptr += 3; + + acpigen_write_if_lequal_op_int(ctx, LOCAL1_OP, 5); + acpigen_pop_len(ctx); + ut_asserteq(IF_OP, *ptr++); + ut_asserteq(7, acpi_test_get_length(ptr)); + ptr += 3; + ut_asserteq(LEQUAL_OP, *ptr++); + ut_asserteq(LOCAL1_OP, *ptr++); + ut_asserteq(BYTE_PREFIX, *ptr++); + ut_asserteq(5, *ptr++); + + ut_asserteq_ptr(ptr, ctx->current); + + free_context(&ctx); + + return 0; +} +DM_TEST(dm_test_acpi_write_cond, 0); + +/* Test emitting writing return values and ToBuffer/ToInteger */ +static int dm_test_acpi_write_return(struct unit_test_state *uts) +{ + int len = sizeof(TEST_STRING); + struct acpi_ctx *ctx; + u8 *ptr; + + ut_assertok(alloc_context(&ctx)); + + ptr = acpigen_get_current(ctx); + acpigen_write_to_buffer(ctx, ARG0_OP, LOCAL0_OP); + ut_asserteq(TO_BUFFER_OP, *ptr++); + ut_asserteq(ARG0_OP, *ptr++); + ut_asserteq(LOCAL0_OP, *ptr++); + + acpigen_write_to_integer(ctx, ARG0_OP, LOCAL0_OP); + ut_asserteq(TO_INTEGER_OP, *ptr++); + ut_asserteq(ARG0_OP, *ptr++); + ut_asserteq(LOCAL0_OP, *ptr++); + + acpigen_write_return_byte_buffer(ctx, (u8 *)TEST_STRING, len); + ut_asserteq(RETURN_OP, *ptr++); + ut_asserteq(BUFFER_OP, *ptr++); + ut_asserteq(5 + len, acpi_test_get_length(ptr)); + ptr += 3; + ut_asserteq(BYTE_PREFIX, *ptr++); + ut_asserteq(len, *ptr++); + ut_asserteq_mem(TEST_STRING, ptr, len); + ptr += len; + + acpigen_write_return_singleton_buffer(ctx, 123); + len = 1; + ut_asserteq(RETURN_OP, *ptr++); + ut_asserteq(BUFFER_OP, *ptr++); + ut_asserteq(4 + len, acpi_test_get_length(ptr)); + ptr += 3; + ut_asserteq(ONE_OP, *ptr++); + ut_asserteq(123, *ptr++); + + acpigen_write_return_byte(ctx, 43); + ut_asserteq(RETURN_OP, *ptr++); + ut_asserteq(BYTE_PREFIX, *ptr++); + ut_asserteq(43, *ptr++); + + ut_asserteq_ptr(ptr, ctx->current); + + free_context(&ctx); + + return 0; +} +DM_TEST(dm_test_acpi_write_return, 0); + +/* Test emitting a DSM for an I2C HID */ +static int dm_test_acpi_write_i2c_dsm(struct unit_test_state *uts) +{ + char uuid_str[UUID_STR_LEN + 1]; + const int reg_offset = 0x20; + struct acpi_ctx *ctx; + u8 *ptr; + + ut_assertok(alloc_context(&ctx)); + + ptr = acpigen_get_current(ctx); + ut_assertok(acpi_device_write_dsm_i2c_hid(ctx, reg_offset)); + + /* acpigen_write_dsm_start() */ + ut_asserteq(METHOD_OP, *ptr++); + ut_asserteq(0x78, acpi_test_get_length(ptr)); + ptr += 3; + ut_asserteq_strn("_DSM", (char *)ptr); + ptr += 4; + ut_asserteq(ACPI_METHOD_SERIALIZED_MASK | 4, *ptr++); + + ut_asserteq(TO_BUFFER_OP, *ptr++); + ut_asserteq(ARG0_OP, *ptr++); + ut_asserteq(LOCAL0_OP, *ptr++); + + /* acpigen_write_dsm_uuid_start() */ + ut_asserteq(IF_OP, *ptr++); + ut_asserteq(0x65, acpi_test_get_length(ptr)); + ptr += 3; + ut_asserteq(LEQUAL_OP, *ptr++); + ut_asserteq(LOCAL0_OP, *ptr++); + + ut_asserteq(BUFFER_OP, *ptr++); + ut_asserteq(UUID_BIN_LEN + 6, acpi_test_get_length(ptr)); + ptr += 3; + ut_asserteq(WORD_PREFIX, *ptr++); + ut_asserteq(UUID_BIN_LEN, get_unaligned((u16 *)ptr)); + ptr += 2; + uuid_bin_to_str(ptr, uuid_str, UUID_STR_FORMAT_GUID); + ut_asserteq_str(ACPI_DSM_I2C_HID_UUID, uuid_str); + ptr += UUID_BIN_LEN; + + ut_asserteq(TO_INTEGER_OP, *ptr++); + ut_asserteq(ARG2_OP, *ptr++); + ut_asserteq(LOCAL1_OP, *ptr++); + + /* acpigen_write_dsm_uuid_start_cond() */ + ut_asserteq(IF_OP, *ptr++); + ut_asserteq(0x34, acpi_test_get_length(ptr)); + ptr += 3; + ut_asserteq(LEQUAL_OP, *ptr++); + ut_asserteq(LOCAL1_OP, *ptr++); + ut_asserteq(ZERO_OP, *ptr++); + + /* + * See code from acpi_device_write_dsm_i2c_hid(). We don't check every + * piece + */ + ut_asserteq(TO_INTEGER_OP, *ptr++); + ut_asserteq(ARG1_OP, *ptr++); + ut_asserteq(LOCAL2_OP, *ptr++); + + ut_asserteq(IF_OP, *ptr++); + ut_asserteq(0xd, acpi_test_get_length(ptr)); + ptr += 3; + ut_asserteq(LEQUAL_OP, *ptr++); + ut_asserteq(LOCAL2_OP, *ptr++); + ut_asserteq(ZERO_OP, *ptr++); /* function 0 */ + + ut_asserteq(RETURN_OP, *ptr++); + ut_asserteq(BUFFER_OP, *ptr++); + ptr += 5; + + ut_asserteq(ELSE_OP, *ptr++); + ptr += 3; + + ut_asserteq(IF_OP, *ptr++); + ut_asserteq(0xd, acpi_test_get_length(ptr)); + ptr += 3; + ut_asserteq(LEQUAL_OP, *ptr++); + ut_asserteq(LOCAL2_OP, *ptr++); + ut_asserteq(ONE_OP, *ptr++); + + ut_asserteq(RETURN_OP, *ptr++); + ut_asserteq(BUFFER_OP, *ptr++); + ptr += 5; + + ut_asserteq(ELSE_OP, *ptr++); + ptr += 3; + + ut_asserteq(RETURN_OP, *ptr++); + ut_asserteq(BUFFER_OP, *ptr++); + ptr += 5; + + /* acpigen_write_dsm_uuid_start_cond() */ + ut_asserteq(IF_OP, *ptr++); + ut_asserteq(9, acpi_test_get_length(ptr)); + ptr += 3; + ut_asserteq(LEQUAL_OP, *ptr++); + ut_asserteq(LOCAL1_OP, *ptr++); + ut_asserteq(ONE_OP, *ptr++); /* function 1 */ + + ut_asserteq(RETURN_OP, *ptr++); + ut_asserteq(BYTE_PREFIX, *ptr++); + ut_asserteq(reg_offset, *ptr++); + + /* acpigen_write_dsm_uuid_end() */ + ut_asserteq(RETURN_OP, *ptr++); + ut_asserteq(BUFFER_OP, *ptr++); + ptr += 5; + + /* acpigen_write_dsm_end */ + ut_asserteq(RETURN_OP, *ptr++); + ut_asserteq(BUFFER_OP, *ptr++); + ptr += 5; + + ut_asserteq_ptr(ptr, ctx->current); + + free_context(&ctx); + + return 0; +} +DM_TEST(dm_test_acpi_write_i2c_dsm, 0); + +/* Test emitting a processor */ +static int dm_test_acpi_write_processor(struct unit_test_state *uts) +{ + const int cpuindex = 6; + const u32 pblock_addr = 0x12345600; + const u32 pblock_len = 0x60; + struct acpi_ctx *ctx; + u8 *ptr; + + ut_assertok(alloc_context(&ctx)); + + ptr = acpigen_get_current(ctx); + acpigen_write_processor(ctx, cpuindex, pblock_addr, pblock_len); + acpigen_pop_len(ctx); + + ut_asserteq(EXT_OP_PREFIX, *ptr++); + ut_asserteq(PROCESSOR_OP, *ptr++); + ut_asserteq(0x13, acpi_test_get_length(ptr)); + ptr += 3; + ut_asserteq_strn("\\._PR_CP06", (char *)ptr); + ptr += 10; + ut_asserteq(cpuindex, *ptr++); + ut_asserteq(pblock_addr, get_unaligned((u32 *)ptr)); + ptr += 4; + ut_asserteq(pblock_len, *ptr++); + + ut_asserteq_ptr(ptr, ctx->current); + + free_context(&ctx); + + return 0; +} +DM_TEST(dm_test_acpi_write_processor, 0); + +/* Test emitting a processor package */ +static int dm_test_acpi_write_processor_package(struct unit_test_state *uts) +{ + const int core_count = 3; + struct acpi_ctx *ctx; + u8 *ptr; + + ut_assertok(alloc_context(&ctx)); + + ptr = acpigen_get_current(ctx); + acpigen_write_processor_package(ctx, "XCPU", 0, core_count); + + ut_asserteq(NAME_OP, *ptr++); + ut_asserteq_strn("XCPU", (char *)ptr); + ptr += 4; + ut_asserteq(PACKAGE_OP, *ptr++); + ptr += 3; /* skip length */ + ut_asserteq(core_count, *ptr++); + + ut_asserteq_strn("\\._PR_CP00", (char *)ptr); + ptr += 10; + ut_asserteq_strn("\\._PR_CP01", (char *)ptr); + ptr += 10; + ut_asserteq_strn("\\._PR_CP02", (char *)ptr); + ptr += 10; + + ut_asserteq_ptr(ptr, ctx->current); + + free_context(&ctx); + + return 0; +} +DM_TEST(dm_test_acpi_write_processor_package, 0); + +/* Test emitting a processor notification package */ +static int dm_test_acpi_write_processor_cnot(struct unit_test_state *uts) +{ + const int core_count = 3; + struct acpi_ctx *ctx; + u8 *ptr; + + ut_assertok(alloc_context(&ctx)); + + ptr = acpigen_get_current(ctx); + acpigen_write_processor_cnot(ctx, core_count); + + ut_asserteq(METHOD_OP, *ptr++); + ptr += 3; /* skip length */ + ut_asserteq_strn("\\._PR_CNOT", (char *)ptr); + ptr += 10; + ut_asserteq(1, *ptr++); + + ut_asserteq(NOTIFY_OP, *ptr++); + ut_asserteq_strn("\\._PR_CP00", (char *)ptr); + ptr += 10; + ut_asserteq(ARG0_OP, *ptr++); + ut_asserteq(NOTIFY_OP, *ptr++); + ut_asserteq_strn("\\._PR_CP01", (char *)ptr); + ptr += 10; + ut_asserteq(ARG0_OP, *ptr++); + ut_asserteq(NOTIFY_OP, *ptr++); + ut_asserteq_strn("\\._PR_CP02", (char *)ptr); + ptr += 10; + ut_asserteq(ARG0_OP, *ptr++); + + ut_asserteq_ptr(ptr, ctx->current); + + free_context(&ctx); + + return 0; +} +DM_TEST(dm_test_acpi_write_processor_cnot, 0); + +/* Test acpigen_write_tpc */ +static int dm_test_acpi_write_tpc(struct unit_test_state *uts) +{ + struct acpi_ctx *ctx; + u8 *ptr; + + ut_assertok(alloc_context(&ctx)); + + ptr = acpigen_get_current(ctx); + acpigen_write_tpc(ctx, "\\TLVL"); + + ut_asserteq(METHOD_OP, *ptr++); + ptr += 3; /* skip length */ + ut_asserteq_strn("_TPC", (char *)ptr); + ptr += 4; + ut_asserteq(0, *ptr++); + ut_asserteq(RETURN_OP, *ptr++); + ut_asserteq_strn("\\TLVL", (char *)ptr); + ptr += 5; + + ut_asserteq_ptr(ptr, ctx->current); + + free_context(&ctx); + + return 0; +} +DM_TEST(dm_test_acpi_write_tpc, 0); + +/* Test acpigen_write_pss_package(), etc. */ +static int dm_test_acpi_write_pss_psd(struct unit_test_state *uts) +{ + struct acpi_ctx *ctx; + u8 *ptr; + + ut_assertok(alloc_context(&ctx)); + + ptr = acpigen_get_current(ctx); + acpigen_write_pss_package(ctx, 1, 2, 3, 4, 5, 6); + ut_asserteq(PACKAGE_OP, *ptr++); + ptr += 3; /* skip length */ + ut_asserteq(6, *ptr++); + + ut_asserteq(DWORD_PREFIX, *ptr++); + ut_asserteq(1, get_unaligned((u32 *)ptr)); + ptr += 5; + + ut_asserteq(2, get_unaligned((u32 *)ptr)); + ptr += 5; + + ut_asserteq(3, get_unaligned((u32 *)ptr)); + ptr += 5; + + ut_asserteq(4, get_unaligned((u32 *)ptr)); + ptr += 5; + + ut_asserteq(5, get_unaligned((u32 *)ptr)); + ptr += 5; + + ut_asserteq(6, get_unaligned((u32 *)ptr)); + ptr += 4; + + acpigen_write_psd_package(ctx, 6, 7, HW_ALL); + ut_asserteq(NAME_OP, *ptr++); + ut_asserteq_strn("_PSD", (char *)ptr); + ptr += 4; + ut_asserteq(PACKAGE_OP, *ptr++); + ptr += 3; /* skip length */ + ut_asserteq(1, *ptr++); + ut_asserteq(PACKAGE_OP, *ptr++); + ptr += 3; /* skip length */ + ut_asserteq(5, *ptr++); + + ut_asserteq(BYTE_PREFIX, *ptr++); + ut_asserteq(5, *ptr++); + ut_asserteq(BYTE_PREFIX, *ptr++); + ut_asserteq(0, *ptr++); + + ut_asserteq(DWORD_PREFIX, *ptr++); + ut_asserteq(6, get_unaligned((u32 *)ptr)); + ptr += 5; + + ut_asserteq(HW_ALL, get_unaligned((u32 *)ptr)); + ptr += 5; + + ut_asserteq(7, get_unaligned((u32 *)ptr)); + ptr += 4; + + ut_asserteq_ptr(ptr, ctx->current); + + free_context(&ctx); + + return 0; +} +DM_TEST(dm_test_acpi_write_pss_psd, 0); + +/* Test acpi_write_cst_package() */ +static int dm_test_acpi_write_cst(struct unit_test_state *uts) +{ + static struct acpi_cstate cstate_map[] = { + { + /* C1 */ + .ctype = 1, /* ACPI C1 */ + .latency = 1, + .power = 1000, + .resource = { + .space_id = ACPI_ADDRESS_SPACE_FIXED, + }, + }, { + .ctype = 2, /* ACPI C2 */ + .latency = 50, + .power = 10, + .resource = { + .space_id = ACPI_ADDRESS_SPACE_IO, + .bit_width = 8, + .addrl = 0x415, + }, + }, + }; + int nentries = ARRAY_SIZE(cstate_map); + struct acpi_ctx *ctx; + u8 *ptr; + int i; + + ut_assertok(alloc_context(&ctx)); + + ptr = acpigen_get_current(ctx); + acpigen_write_cst_package(ctx, cstate_map, nentries); + + ut_asserteq(NAME_OP, *ptr++); + ut_asserteq_strn("_CST", (char *)ptr); + ptr += 4; + ut_asserteq(PACKAGE_OP, *ptr++); + ptr += 3; /* skip length */ + ut_asserteq(nentries + 1, *ptr++); + ut_asserteq(DWORD_PREFIX, *ptr++); + ut_asserteq(nentries, get_unaligned((u32 *)ptr)); + ptr += 4; + + for (i = 0; i < nentries; i++) { + ut_asserteq(PACKAGE_OP, *ptr++); + ptr += 3; /* skip length */ + ut_asserteq(4, *ptr++); + ut_asserteq(BUFFER_OP, *ptr++); + ptr += 0x17; + ut_asserteq(DWORD_PREFIX, *ptr++); + ut_asserteq(cstate_map[i].ctype, get_unaligned((u32 *)ptr)); + ptr += 5; + ut_asserteq(cstate_map[i].latency, get_unaligned((u32 *)ptr)); + ptr += 5; + ut_asserteq(cstate_map[i].power, get_unaligned((u32 *)ptr)); + ptr += 4; + } + + ut_asserteq_ptr(ptr, ctx->current); + + free_context(&ctx); + + return 0; +} +DM_TEST(dm_test_acpi_write_cst, 0); + +/* Test acpi_write_cst_package() */ +static int dm_test_acpi_write_csd(struct unit_test_state *uts) +{ + struct acpi_ctx *ctx; + u8 *ptr; + + ut_assertok(alloc_context(&ctx)); + + ptr = acpigen_get_current(ctx); + acpigen_write_csd_package(ctx, 12, 34, CSD_HW_ALL, 56); + + ut_asserteq(NAME_OP, *ptr++); + ut_asserteq_strn("_CSD", (char *)ptr); + ptr += 4; + ut_asserteq(PACKAGE_OP, *ptr++); + ptr += 3; /* skip length */ + ut_asserteq(1, *ptr++); + ut_asserteq(PACKAGE_OP, *ptr++); + ptr += 3; /* skip length */ + ut_asserteq(6, *ptr++); + + ut_asserteq(BYTE_PREFIX, *ptr++); + ut_asserteq(6, *ptr++); + ut_asserteq(BYTE_PREFIX, *ptr++); + ut_asserteq(0, *ptr++); + ut_asserteq(DWORD_PREFIX, *ptr++); + ut_asserteq(12, get_unaligned((u32 *)ptr)); + ptr += 5; + ut_asserteq(CSD_HW_ALL, get_unaligned((u32 *)ptr)); + ptr += 5; + ut_asserteq(34, get_unaligned((u32 *)ptr)); + ptr += 5; + ut_asserteq(56, get_unaligned((u32 *)ptr)); + ptr += 4; + + ut_asserteq_ptr(ptr, ctx->current); + + free_context(&ctx); + + return 0; +} +DM_TEST(dm_test_acpi_write_csd, 0); + +/* Test acpigen_write_tss_package() */ +static int dm_test_acpi_write_tss(struct unit_test_state *uts) +{ + static struct acpi_tstate tstate_list[] = { + { 1, 2, 3, 4, 5, }, + { 6, 7, 8, 9, 10, }, + }; + int nentries = ARRAY_SIZE(tstate_list); + struct acpi_ctx *ctx; + u8 *ptr; + int i; + + ut_assertok(alloc_context(&ctx)); + + ptr = acpigen_get_current(ctx); + acpigen_write_tss_package(ctx, tstate_list, nentries); + + ut_asserteq(NAME_OP, *ptr++); + ut_asserteq_strn("_TSS", (char *)ptr); + ptr += 4; + ut_asserteq(PACKAGE_OP, *ptr++); + ptr += 3; /* skip length */ + ut_asserteq(nentries, *ptr++); + + for (i = 0; i < nentries; i++) { + ut_asserteq(PACKAGE_OP, *ptr++); + ptr += 3; /* skip length */ + ut_asserteq(5, *ptr++); + ut_asserteq(DWORD_PREFIX, *ptr++); + ut_asserteq(tstate_list[i].percent, get_unaligned((u32 *)ptr)); + ptr += 5; + ut_asserteq(tstate_list[i].power, get_unaligned((u32 *)ptr)); + ptr += 5; + ut_asserteq(tstate_list[i].latency, get_unaligned((u32 *)ptr)); + ptr += 5; + ut_asserteq(tstate_list[i].control, get_unaligned((u32 *)ptr)); + ptr += 5; + ut_asserteq(tstate_list[i].status, get_unaligned((u32 *)ptr)); + ptr += 4; + } + + ut_asserteq_ptr(ptr, ctx->current); + + free_context(&ctx); + + return 0; +} +DM_TEST(dm_test_acpi_write_tss, 0); + +/* Test acpigen_write_tsd_package() */ +static int dm_test_acpi_write_tsd_package(struct unit_test_state *uts) +{ + struct acpi_ctx *ctx; + u8 *ptr; + + ut_assertok(alloc_context(&ctx)); + + ptr = acpigen_get_current(ctx); + acpigen_write_tsd_package(ctx, 12, 34, HW_ALL); + + ut_asserteq(NAME_OP, *ptr++); + ut_asserteq_strn("_TSD", (char *)ptr); + ptr += 4; + ut_asserteq(PACKAGE_OP, *ptr++); + ptr += 3; /* skip length */ + ut_asserteq(1, *ptr++); + ut_asserteq(PACKAGE_OP, *ptr++); + ptr += 3; /* skip length */ + ut_asserteq(5, *ptr++); + + ut_asserteq(BYTE_PREFIX, *ptr++); + ut_asserteq(5, *ptr++); + ut_asserteq(BYTE_PREFIX, *ptr++); + ut_asserteq(0, *ptr++); + ut_asserteq(DWORD_PREFIX, *ptr++); + ut_asserteq(12, get_unaligned((u32 *)ptr)); + ptr += 5; + ut_asserteq(CSD_HW_ALL, get_unaligned((u32 *)ptr)); + ptr += 5; + ut_asserteq(34, get_unaligned((u32 *)ptr)); + ptr += 4; + + ut_asserteq_ptr(ptr, ctx->current); + + free_context(&ctx); + + return 0; +} +DM_TEST(dm_test_acpi_write_tsd_package, 0); diff --git a/roms/u-boot/test/dm/adc.c b/roms/u-boot/test/dm/adc.c new file mode 100644 index 000000000..740167e16 --- /dev/null +++ b/roms/u-boot/test/dm/adc.c @@ -0,0 +1,198 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Tests for the driver model ADC API + * + * Copyright (c) 2015 Samsung Electronics + * Przemyslaw Marczak <p.marczak@samsung.com> + */ + +#include <common.h> +#include <adc.h> +#include <dm.h> +#include <dm/root.h> +#include <dm/util.h> +#include <dm/test.h> +#include <errno.h> +#include <fdtdec.h> +#include <power/regulator.h> +#include <power/sandbox_pmic.h> +#include <sandbox-adc.h> +#include <test/test.h> +#include <test/ut.h> + +static int dm_test_adc_bind(struct unit_test_state *uts) +{ + struct udevice *dev; + unsigned int channel_mask; + + ut_assertok(uclass_get_device_by_name(UCLASS_ADC, "adc@0", &dev)); + ut_asserteq_str(SANDBOX_ADC_DEVNAME, dev->name); + + ut_assertok(adc_channel_mask(dev, &channel_mask)); + ut_asserteq((1 << SANDBOX_ADC_CHANNELS) - 1, channel_mask); + + return 0; +} +DM_TEST(dm_test_adc_bind, UT_TESTF_SCAN_FDT); + +static int dm_test_adc_wrong_channel_selection(struct unit_test_state *uts) +{ + struct udevice *dev; + + ut_assertok(uclass_get_device_by_name(UCLASS_ADC, "adc@0", &dev)); + ut_asserteq(-EINVAL, adc_start_channel(dev, SANDBOX_ADC_CHANNELS)); + + return 0; +} +DM_TEST(dm_test_adc_wrong_channel_selection, UT_TESTF_SCAN_FDT); + +static int dm_test_adc_supply(struct unit_test_state *uts) +{ + struct udevice *supply; + struct udevice *dev; + int uV; + + ut_assertok(uclass_get_device_by_name(UCLASS_ADC, "adc@0", &dev)); + + /* Test Vss value - predefined 0 uV */ + ut_assertok(adc_vss_value(dev, &uV)); + ut_asserteq(SANDBOX_ADC_VSS_VALUE, uV); + + /* Test Vdd initial value - buck2 */ + ut_assertok(adc_vdd_value(dev, &uV)); + ut_asserteq(SANDBOX_BUCK2_INITIAL_EXPECTED_UV, uV); + + /* Change Vdd value - buck2 manual preset */ + ut_assertok(regulator_get_by_devname(SANDBOX_BUCK2_DEVNAME, &supply)); + ut_assertok(regulator_set_value(supply, SANDBOX_BUCK2_SET_UV)); + ut_asserteq(SANDBOX_BUCK2_SET_UV, regulator_get_value(supply)); + + /* Update ADC plat and get new Vdd value */ + ut_assertok(adc_vdd_value(dev, &uV)); + ut_asserteq(SANDBOX_BUCK2_SET_UV, uV); + + /* Disable buck2 and test ADC supply enable function */ + ut_assertok(regulator_set_enable(supply, false)); + ut_asserteq(false, regulator_get_enable(supply)); + /* adc_start_channel() should enable the supply regulator */ + ut_assertok(adc_start_channel(dev, 0)); + ut_asserteq(true, regulator_get_enable(supply)); + + return 0; +} +DM_TEST(dm_test_adc_supply, UT_TESTF_SCAN_FDT); + +struct adc_channel adc_channel_test_data[] = { + { 0, SANDBOX_ADC_CHANNEL0_DATA }, + { 1, SANDBOX_ADC_CHANNEL1_DATA }, + { 2, SANDBOX_ADC_CHANNEL2_DATA }, + { 3, SANDBOX_ADC_CHANNEL3_DATA }, +}; + +static int dm_test_adc_single_channel_conversion(struct unit_test_state *uts) +{ + struct adc_channel *tdata = adc_channel_test_data; + unsigned int i, data; + struct udevice *dev; + + ut_assertok(uclass_get_device_by_name(UCLASS_ADC, "adc@0", &dev)); + /* Test each ADC channel's value */ + for (i = 0; i < SANDBOX_ADC_CHANNELS; i++, tdata++) { + ut_assertok(adc_start_channel(dev, tdata->id)); + ut_assertok(adc_channel_data(dev, tdata->id, &data)); + ut_asserteq(tdata->data, data); + } + + return 0; +} +DM_TEST(dm_test_adc_single_channel_conversion, UT_TESTF_SCAN_FDT); + +static int dm_test_adc_multi_channel_conversion(struct unit_test_state *uts) +{ + struct adc_channel channels[SANDBOX_ADC_CHANNELS]; + struct udevice *dev; + struct adc_channel *tdata = adc_channel_test_data; + unsigned int i, channel_mask; + + channel_mask = ADC_CHANNEL(0) | ADC_CHANNEL(1) | + ADC_CHANNEL(2) | ADC_CHANNEL(3); + + /* Start multi channel conversion */ + ut_assertok(uclass_get_device_by_name(UCLASS_ADC, "adc@0", &dev)); + ut_assertok(adc_start_channels(dev, channel_mask)); + ut_assertok(adc_channels_data(dev, channel_mask, channels)); + + /* Compare the expected and returned conversion data. */ + for (i = 0; i < SANDBOX_ADC_CHANNELS; i++, tdata++) + ut_asserteq(tdata->data, channels[i].data); + + return 0; +} +DM_TEST(dm_test_adc_multi_channel_conversion, UT_TESTF_SCAN_FDT); + +static int dm_test_adc_single_channel_shot(struct unit_test_state *uts) +{ + struct adc_channel *tdata = adc_channel_test_data; + unsigned int i, data; + + for (i = 0; i < SANDBOX_ADC_CHANNELS; i++, tdata++) { + /* Start single channel conversion */ + ut_assertok(adc_channel_single_shot("adc@0", tdata->id, &data)); + /* Compare the expected and returned conversion data. */ + ut_asserteq(tdata->data, data); + } + + return 0; +} +DM_TEST(dm_test_adc_single_channel_shot, UT_TESTF_SCAN_FDT); + +static int dm_test_adc_multi_channel_shot(struct unit_test_state *uts) +{ + struct adc_channel channels[SANDBOX_ADC_CHANNELS]; + struct adc_channel *tdata = adc_channel_test_data; + unsigned int i, channel_mask; + + channel_mask = ADC_CHANNEL(0) | ADC_CHANNEL(1) | + ADC_CHANNEL(2) | ADC_CHANNEL(3); + + /* Start single call and multi channel conversion */ + ut_assertok(adc_channels_single_shot("adc@0", channel_mask, channels)); + + /* Compare the expected and returned conversion data. */ + for (i = 0; i < SANDBOX_ADC_CHANNELS; i++, tdata++) + ut_asserteq(tdata->data, channels[i].data); + + return 0; +} +DM_TEST(dm_test_adc_multi_channel_shot, UT_TESTF_SCAN_FDT); + +static const int dm_test_adc_uV_data[SANDBOX_ADC_CHANNELS] = { + ((u64)SANDBOX_ADC_CHANNEL0_DATA * SANDBOX_BUCK2_INITIAL_EXPECTED_UV) / + SANDBOX_ADC_DATA_MASK, + ((u64)SANDBOX_ADC_CHANNEL1_DATA * SANDBOX_BUCK2_INITIAL_EXPECTED_UV) / + SANDBOX_ADC_DATA_MASK, + ((u64)SANDBOX_ADC_CHANNEL2_DATA * SANDBOX_BUCK2_INITIAL_EXPECTED_UV) / + SANDBOX_ADC_DATA_MASK, + ((u64)SANDBOX_ADC_CHANNEL3_DATA * SANDBOX_BUCK2_INITIAL_EXPECTED_UV) / + SANDBOX_ADC_DATA_MASK, +}; + +static int dm_test_adc_raw_to_uV(struct unit_test_state *uts) +{ + struct adc_channel *tdata = adc_channel_test_data; + unsigned int i, data; + struct udevice *dev; + int uV; + + ut_assertok(uclass_get_device_by_name(UCLASS_ADC, "adc@0", &dev)); + /* Test each ADC channel's value in microvolts */ + for (i = 0; i < SANDBOX_ADC_CHANNELS; i++, tdata++) { + ut_assertok(adc_start_channel(dev, tdata->id)); + ut_assertok(adc_channel_data(dev, tdata->id, &data)); + ut_assertok(adc_raw_to_uV(dev, data, &uV)); + ut_asserteq(dm_test_adc_uV_data[i], uV); + } + + return 0; +} +DM_TEST(dm_test_adc_raw_to_uV, UT_TESTF_SCAN_FDT); diff --git a/roms/u-boot/test/dm/audio.c b/roms/u-boot/test/dm/audio.c new file mode 100644 index 000000000..add15ae20 --- /dev/null +++ b/roms/u-boot/test/dm/audio.c @@ -0,0 +1,35 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright 2018 Google LLC + * Written by Simon Glass <sjg@chromium.org> + */ + +#include <common.h> +#include <audio_codec.h> +#include <dm.h> +#include <dm/test.h> +#include <test/test.h> +#include <test/ut.h> +#include <asm/test.h> + +/* Basic test of the audio codec uclass */ +static int dm_test_audio(struct unit_test_state *uts) +{ + int interface, rate, mclk_freq, bits_per_sample; + struct udevice *dev; + uint channels; + + /* check probe success */ + ut_assertok(uclass_first_device_err(UCLASS_AUDIO_CODEC, &dev)); + ut_assertok(audio_codec_set_params(dev, 1, 2, 3, 4, 5)); + sandbox_get_codec_params(dev, &interface, &rate, &mclk_freq, + &bits_per_sample, &channels); + ut_asserteq(1, interface); + ut_asserteq(2, rate); + ut_asserteq(3, mclk_freq); + ut_asserteq(4, bits_per_sample); + ut_asserteq(5, channels); + + return 0; +} +DM_TEST(dm_test_audio, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); diff --git a/roms/u-boot/test/dm/axi.c b/roms/u-boot/test/dm/axi.c new file mode 100644 index 000000000..dc029df5e --- /dev/null +++ b/roms/u-boot/test/dm/axi.c @@ -0,0 +1,79 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * (C) Copyright 2018 + * Mario Six, Guntermann & Drunck GmbH, mario.six@gdsys.cc + */ + +#include <common.h> +#include <axi.h> +#include <dm.h> +#include <log.h> +#include <asm/axi.h> +#include <dm/test.h> +#include <test/test.h> +#include <test/ut.h> + +/* Test that sandbox AXI works correctly */ +static int dm_test_axi_base(struct unit_test_state *uts) +{ + struct udevice *bus; + + ut_assertok(uclass_get_device(UCLASS_AXI, 0, &bus)); + + return 0; +} + +DM_TEST(dm_test_axi_base, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); + +/* Test that sandbox PCI bus numbering works correctly */ +static int dm_test_axi_busnum(struct unit_test_state *uts) +{ + struct udevice *bus; + + ut_assertok(uclass_get_device_by_seq(UCLASS_AXI, 0, &bus)); + + return 0; +} + +DM_TEST(dm_test_axi_busnum, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); + +/* Test that we can use the store device correctly */ +static int dm_test_axi_store(struct unit_test_state *uts) +{ + struct udevice *store; + u8 tdata1[] = {0x55, 0x66, 0x77, 0x88}; + u8 tdata2[] = {0xaa, 0xbb, 0xcc, 0xdd}; + u32 val; + u8 *data; + + /* Check that asking for the device automatically fires up AXI */ + ut_assertok(uclass_get_device(UCLASS_AXI_EMUL, 0, &store)); + ut_assert(device_active(store)); + + axi_get_store(store, &data); + + /* Test reading */ + memcpy(data, tdata1, ARRAY_SIZE(tdata1)); + axi_read(store, 0, &val, AXI_SIZE_32); + ut_asserteq(0x55667788, val); + + memcpy(data + 3, tdata2, ARRAY_SIZE(tdata2)); + axi_read(store, 3, &val, AXI_SIZE_32); + ut_asserteq(0xaabbccdd, val); + + /* Reset data store */ + memset(data, 0, 16); + + /* Test writing */ + val = 0x55667788; + axi_write(store, 0, &val, AXI_SIZE_32); + ut_asserteq_mem(data, tdata1, ARRAY_SIZE(tdata1)); + + val = 0xaabbccdd; + axi_write(store, 3, &val, AXI_SIZE_32); + ut_asserteq_mem(data + 3, tdata2, ARRAY_SIZE(tdata1)); + + return 0; +} + +DM_TEST(dm_test_axi_store, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); diff --git a/roms/u-boot/test/dm/blk.c b/roms/u-boot/test/dm/blk.c new file mode 100644 index 000000000..b7f4304e9 --- /dev/null +++ b/roms/u-boot/test/dm/blk.c @@ -0,0 +1,164 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2015 Google, Inc + */ + +#include <common.h> +#include <dm.h> +#include <part.h> +#include <usb.h> +#include <asm/global_data.h> +#include <asm/state.h> +#include <dm/test.h> +#include <test/test.h> +#include <test/ut.h> + +DECLARE_GLOBAL_DATA_PTR; + +/* Test that block devices can be created */ +static int dm_test_blk_base(struct unit_test_state *uts) +{ + struct udevice *blk1, *blk3, *dev; + + /* Create two, one the parent of the other */ + ut_assertok(blk_create_device(gd->dm_root, "sandbox_host_blk", "test", + IF_TYPE_HOST, 1, 512, 2, &blk1)); + ut_assertok(blk_create_device(blk1, "sandbox_host_blk", "test", + IF_TYPE_HOST, 3, 512, 2, &blk3)); + + /* Check we can find them */ + ut_asserteq(-ENODEV, blk_get_device(IF_TYPE_HOST, 0, &dev)); + ut_assertok(blk_get_device(IF_TYPE_HOST, 1, &dev)); + ut_asserteq_ptr(blk1, dev); + ut_assertok(blk_get_device(IF_TYPE_HOST, 3, &dev)); + ut_asserteq_ptr(blk3, dev); + + /* Check we can iterate */ + ut_assertok(blk_first_device(IF_TYPE_HOST, &dev)); + ut_asserteq_ptr(blk1, dev); + ut_assertok(blk_next_device(&dev)); + ut_asserteq_ptr(blk3, dev); + + return 0; +} +DM_TEST(dm_test_blk_base, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); + +static int count_blk_devices(void) +{ + struct udevice *blk; + struct uclass *uc; + int count = 0; + int ret; + + ret = uclass_get(UCLASS_BLK, &uc); + if (ret) + return ret; + + uclass_foreach_dev(blk, uc) + count++; + + return count; +} + +/* Test that block devices work correctly with USB */ +static int dm_test_blk_usb(struct unit_test_state *uts) +{ + struct udevice *usb_dev, *dev; + struct blk_desc *dev_desc; + + /* Get a flash device */ + state_set_skip_delays(true); + ut_assertok(usb_init()); + ut_assertok(uclass_get_device(UCLASS_MASS_STORAGE, 0, &usb_dev)); + ut_assertok(blk_get_device_by_str("usb", "0", &dev_desc)); + + /* The parent should be a block device */ + ut_assertok(blk_get_device(IF_TYPE_USB, 0, &dev)); + ut_asserteq_ptr(usb_dev, dev_get_parent(dev)); + + /* Check we have one block device for each mass storage device */ + ut_asserteq(6, count_blk_devices()); + + /* Now go around again, making sure the old devices were unbound */ + ut_assertok(usb_stop()); + ut_assertok(usb_init()); + ut_asserteq(6, count_blk_devices()); + ut_assertok(usb_stop()); + + return 0; +} +DM_TEST(dm_test_blk_usb, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); + +/* Test that we can find block devices without probing them */ +static int dm_test_blk_find(struct unit_test_state *uts) +{ + struct udevice *blk, *dev; + + ut_assertok(blk_create_device(gd->dm_root, "sandbox_host_blk", "test", + IF_TYPE_HOST, 1, 512, 2, &blk)); + ut_asserteq(-ENODEV, blk_find_device(IF_TYPE_HOST, 0, &dev)); + ut_assertok(blk_find_device(IF_TYPE_HOST, 1, &dev)); + ut_asserteq_ptr(blk, dev); + ut_asserteq(false, device_active(dev)); + + /* Now activate it */ + ut_assertok(blk_get_device(IF_TYPE_HOST, 1, &dev)); + ut_asserteq_ptr(blk, dev); + ut_asserteq(true, device_active(dev)); + + return 0; +} +DM_TEST(dm_test_blk_find, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); + +/* Test that block device numbering works as expected */ +static int dm_test_blk_devnum(struct unit_test_state *uts) +{ + struct udevice *dev, *mmc_dev, *parent; + int i; + + /* + * Probe the devices, with the first one being probed last. This is the + * one with no alias / sequence numnber. + */ + ut_assertok(uclass_get_device(UCLASS_MMC, 1, &dev)); + ut_assertok(uclass_get_device(UCLASS_MMC, 2, &dev)); + ut_assertok(uclass_get_device(UCLASS_MMC, 0, &dev)); + for (i = 0; i < 3; i++) { + struct blk_desc *desc; + + /* Check that the bblock device is attached */ + ut_assertok(uclass_get_device_by_seq(UCLASS_MMC, i, &mmc_dev)); + ut_assertok(blk_find_device(IF_TYPE_MMC, i, &dev)); + parent = dev_get_parent(dev); + ut_asserteq_ptr(parent, mmc_dev); + ut_asserteq(trailing_strtol(mmc_dev->name), i); + + /* + * Check that the block device devnum matches its parent's + * sequence number + */ + desc = dev_get_uclass_plat(dev); + ut_asserteq(desc->devnum, i); + } + + return 0; +} +DM_TEST(dm_test_blk_devnum, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); + +/* Test that we can get a block from its parent */ +static int dm_test_blk_get_from_parent(struct unit_test_state *uts) +{ + struct udevice *dev, *blk; + + ut_assertok(uclass_get_device(UCLASS_MMC, 0, &dev)); + ut_assertok(blk_get_from_parent(dev, &blk)); + + ut_assertok(uclass_get_device(UCLASS_I2C, 0, &dev)); + ut_asserteq(-ENOTBLK, blk_get_from_parent(dev, &blk)); + + ut_assertok(uclass_get_device(UCLASS_GPIO, 0, &dev)); + ut_asserteq(-ENODEV, blk_get_from_parent(dev, &blk)); + + return 0; +} +DM_TEST(dm_test_blk_get_from_parent, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); diff --git a/roms/u-boot/test/dm/bootcount.c b/roms/u-boot/test/dm/bootcount.c new file mode 100644 index 000000000..e0c47b5d7 --- /dev/null +++ b/roms/u-boot/test/dm/bootcount.c @@ -0,0 +1,40 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * (C) 2018 Theobroma Systems Design und Consulting GmbH + */ + +#include <common.h> +#include <dm.h> +#include <bootcount.h> +#include <log.h> +#include <asm/test.h> +#include <dm/test.h> +#include <test/test.h> +#include <test/ut.h> + +static int dm_test_bootcount(struct unit_test_state *uts) +{ + struct udevice *dev; + u32 val; + + ut_assertok(uclass_get_device(UCLASS_BOOTCOUNT, 0, &dev)); + ut_assertok(dm_bootcount_set(dev, 0)); + ut_assertok(dm_bootcount_get(dev, &val)); + ut_assert(val == 0); + ut_assertok(dm_bootcount_set(dev, 0xab)); + ut_assertok(dm_bootcount_get(dev, &val)); + ut_assert(val == 0xab); + + ut_assertok(uclass_get_device(UCLASS_BOOTCOUNT, 1, &dev)); + ut_assertok(dm_bootcount_set(dev, 0)); + ut_assertok(dm_bootcount_get(dev, &val)); + ut_assert(val == 0); + ut_assertok(dm_bootcount_set(dev, 0xab)); + ut_assertok(dm_bootcount_get(dev, &val)); + ut_assert(val == 0xab); + + return 0; +} + +DM_TEST(dm_test_bootcount, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); + diff --git a/roms/u-boot/test/dm/bus.c b/roms/u-boot/test/dm/bus.c new file mode 100644 index 000000000..89a6aa655 --- /dev/null +++ b/roms/u-boot/test/dm/bus.c @@ -0,0 +1,487 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (c) 2014 Google, Inc + */ + +#include <common.h> +#ifdef CONFIG_SANDBOX +#include <log.h> +#include <os.h> +#endif +#include <dm.h> +#include <asm/global_data.h> +#include <dm/device.h> +#include <dm/device-internal.h> +#include <dm/test.h> +#include <dm/uclass-internal.h> +#include <dm/util.h> +#include <test/test.h> +#include <test/ut.h> + +DECLARE_GLOBAL_DATA_PTR; + +/* Test that we can probe for children */ +static int dm_test_bus_children(struct unit_test_state *uts) +{ + int num_devices = 9; + struct udevice *bus; + struct uclass *uc; + + ut_assertok(uclass_get(UCLASS_TEST_FDT, &uc)); + ut_asserteq(num_devices, list_count_items(&uc->dev_head)); + + /* Probe the bus, which should yield 3 more devices */ + ut_assertok(uclass_get_device(UCLASS_TEST_BUS, 0, &bus)); + num_devices += 3; + + ut_assertok(uclass_get(UCLASS_TEST_FDT, &uc)); + ut_asserteq(num_devices, list_count_items(&uc->dev_head)); + + ut_assert(!dm_check_devices(uts, num_devices)); + + return 0; +} +DM_TEST(dm_test_bus_children, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); + +/* Test our functions for accessing children */ +static int dm_test_bus_children_funcs(struct unit_test_state *uts) +{ + const void *blob = gd->fdt_blob; + struct udevice *bus, *dev; + int node; + + ut_assertok(uclass_get_device(UCLASS_TEST_BUS, 0, &bus)); + + /* device_get_child() */ + ut_assertok(device_get_child(bus, 0, &dev)); + ut_asserteq(-ENODEV, device_get_child(bus, 4, &dev)); + ut_assertok(device_get_child_by_seq(bus, 5, &dev)); + ut_assert(dev_get_flags(dev) & DM_FLAG_ACTIVATED); + ut_asserteq_str("c-test@5", dev->name); + + /* Device with sequence number 0 should be accessible */ + ut_asserteq(-ENODEV, device_find_child_by_seq(bus, -1, &dev)); + ut_assertok(device_find_child_by_seq(bus, 0, &dev)); + ut_assert(!(dev_get_flags(dev) & DM_FLAG_ACTIVATED)); + ut_asserteq(0, device_find_child_by_seq(bus, 0, &dev)); + ut_assertok(device_get_child_by_seq(bus, 0, &dev)); + ut_assert(dev_get_flags(dev) & DM_FLAG_ACTIVATED); + ut_asserteq(0, device_find_child_by_seq(bus, 0, &dev)); + + /* There is no device with sequence number 2 */ + ut_asserteq(-ENODEV, device_find_child_by_seq(bus, 2, &dev)); + ut_asserteq(-ENODEV, device_find_child_by_seq(bus, 2, &dev)); + ut_asserteq(-ENODEV, device_get_child_by_seq(bus, 2, &dev)); + + /* Looking for something that is not a child */ + node = fdt_path_offset(blob, "/junk"); + ut_asserteq(-ENODEV, device_find_child_by_of_offset(bus, node, &dev)); + node = fdt_path_offset(blob, "/d-test"); + ut_asserteq(-ENODEV, device_find_child_by_of_offset(bus, node, &dev)); + + return 0; +} +DM_TEST(dm_test_bus_children_funcs, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); + +static int dm_test_bus_children_of_offset(struct unit_test_state *uts) +{ + const void *blob = gd->fdt_blob; + struct udevice *bus, *dev; + int node; + + ut_assertok(uclass_get_device(UCLASS_TEST_BUS, 0, &bus)); + ut_assertnonnull(bus); + + /* Find a valid child */ + node = fdt_path_offset(blob, "/some-bus/c-test@1"); + ut_assert(node > 0); + ut_assertok(device_find_child_by_of_offset(bus, node, &dev)); + ut_assertnonnull(dev); + ut_assert(!(dev_get_flags(dev) & DM_FLAG_ACTIVATED)); + ut_assertok(device_get_child_by_of_offset(bus, node, &dev)); + ut_assertnonnull(dev); + ut_assert(dev_get_flags(dev) & DM_FLAG_ACTIVATED); + + return 0; +} +DM_TEST(dm_test_bus_children_of_offset, + UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT | UT_TESTF_FLAT_TREE); + +/* Test that we can iterate through children */ +static int dm_test_bus_children_iterators(struct unit_test_state *uts) +{ + struct udevice *bus, *dev, *child; + + /* Walk through the children one by one */ + ut_assertok(uclass_get_device(UCLASS_TEST_BUS, 0, &bus)); + ut_assertok(device_find_first_child(bus, &dev)); + ut_asserteq_str("c-test@5", dev->name); + ut_assertok(device_find_next_child(&dev)); + ut_asserteq_str("c-test@0", dev->name); + ut_assertok(device_find_next_child(&dev)); + ut_asserteq_str("c-test@1", dev->name); + ut_assertok(device_find_next_child(&dev)); + ut_asserteq_ptr(dev, NULL); + + /* Move to the next child without using device_find_first_child() */ + ut_assertok(device_find_child_by_seq(bus, 5, &dev)); + ut_asserteq_str("c-test@5", dev->name); + ut_assertok(device_find_next_child(&dev)); + ut_asserteq_str("c-test@0", dev->name); + + /* Try a device with no children */ + ut_assertok(device_find_first_child(dev, &child)); + ut_asserteq_ptr(child, NULL); + + return 0; +} +DM_TEST(dm_test_bus_children_iterators, + UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); + +/* Test that the bus can store data about each child */ +static int test_bus_parent_data(struct unit_test_state *uts) +{ + struct dm_test_parent_data *parent_data; + struct udevice *bus, *dev; + struct uclass *uc; + int value; + + ut_assertok(uclass_get_device(UCLASS_TEST_BUS, 0, &bus)); + + /* Check that parent data is allocated */ + ut_assertok(device_find_child_by_seq(bus, 0, &dev)); + ut_asserteq_ptr(NULL, dev_get_parent_priv(dev)); + ut_assertok(device_get_child_by_seq(bus, 0, &dev)); + parent_data = dev_get_parent_priv(dev); + ut_assert(NULL != parent_data); + + /* Check that it starts at 0 and goes away when device is removed */ + parent_data->sum += 5; + ut_asserteq(5, parent_data->sum); + device_remove(dev, DM_REMOVE_NORMAL); + ut_asserteq_ptr(NULL, dev_get_parent_priv(dev)); + + /* Check that we can do this twice */ + ut_assertok(device_get_child_by_seq(bus, 0, &dev)); + parent_data = dev_get_parent_priv(dev); + ut_assert(NULL != parent_data); + parent_data->sum += 5; + ut_asserteq(5, parent_data->sum); + + /* Add parent data to all children */ + ut_assertok(uclass_get(UCLASS_TEST_FDT, &uc)); + value = 5; + uclass_foreach_dev(dev, uc) { + /* Ignore these if they are not on this bus */ + if (dev->parent != bus) { + ut_asserteq_ptr(NULL, dev_get_parent_priv(dev)); + continue; + } + ut_assertok(device_probe(dev)); + parent_data = dev_get_parent_priv(dev); + + parent_data->sum = value; + value += 5; + } + + /* Check it is still there */ + value = 5; + uclass_foreach_dev(dev, uc) { + /* Ignore these if they are not on this bus */ + if (dev->parent != bus) + continue; + parent_data = dev_get_parent_priv(dev); + + ut_asserteq(value, parent_data->sum); + value += 5; + } + + return 0; +} +/* Test that the bus can store data about each child */ +static int dm_test_bus_parent_data(struct unit_test_state *uts) +{ + return test_bus_parent_data(uts); +} +DM_TEST(dm_test_bus_parent_data, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); + +/* As above but the size is controlled by the uclass */ +static int dm_test_bus_parent_data_uclass(struct unit_test_state *uts) +{ + struct driver *drv; + struct udevice *bus; + int size; + int ret; + + /* Set the driver size to 0 so that the uclass size is used */ + ut_assertok(uclass_find_device(UCLASS_TEST_BUS, 0, &bus)); + drv = (struct driver *)bus->driver; + size = drv->per_child_auto; + +#ifdef CONFIG_SANDBOX + os_mprotect_allow(bus->uclass->uc_drv, sizeof(*bus->uclass->uc_drv)); + os_mprotect_allow(drv, sizeof(*drv)); +#endif + bus->uclass->uc_drv->per_child_auto = size; + drv->per_child_auto = 0; + ret = test_bus_parent_data(uts); + if (ret) + return ret; + bus->uclass->uc_drv->per_child_auto = 0; + drv->per_child_auto = size; + + return 0; +} +DM_TEST(dm_test_bus_parent_data_uclass, + UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); + +/* Test that the bus ops are called when a child is probed/removed */ +static int dm_test_bus_parent_ops(struct unit_test_state *uts) +{ + struct dm_test_parent_data *parent_data; + struct udevice *bus, *dev; + struct uclass *uc; + + testbus_get_clear_removed(); + ut_assertok(uclass_get_device(UCLASS_TEST_BUS, 0, &bus)); + ut_assertok(uclass_get(UCLASS_TEST_FDT, &uc)); + + uclass_foreach_dev(dev, uc) { + /* Ignore these if they are not on this bus */ + if (dev->parent != bus) + continue; + ut_asserteq_ptr(NULL, dev_get_parent_priv(dev)); + + ut_assertok(device_probe(dev)); + parent_data = dev_get_parent_priv(dev); + ut_asserteq(TEST_FLAG_CHILD_PROBED, parent_data->flag); + } + + uclass_foreach_dev(dev, uc) { + /* Ignore these if they are not on this bus */ + if (dev->parent != bus) + continue; + parent_data = dev_get_parent_priv(dev); + ut_asserteq(TEST_FLAG_CHILD_PROBED, parent_data->flag); + ut_assertok(device_remove(dev, DM_REMOVE_NORMAL)); + ut_asserteq_ptr(NULL, dev_get_parent_priv(dev)); + ut_asserteq_ptr(testbus_get_clear_removed(), dev); + } + + return 0; +} +DM_TEST(dm_test_bus_parent_ops, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); + +static int test_bus_parent_plat(struct unit_test_state *uts) +{ + struct dm_test_parent_plat *plat; + struct udevice *bus, *dev; + + /* Check that the bus has no children */ + ut_assertok(uclass_find_device(UCLASS_TEST_BUS, 0, &bus)); + device_find_first_child(bus, &dev); + ut_asserteq_ptr(NULL, dev); + + ut_assertok(uclass_get_device(UCLASS_TEST_BUS, 0, &bus)); + + for (device_find_first_child(bus, &dev); + dev; + device_find_next_child(&dev)) { + /* Check that platform data is allocated */ + plat = dev_get_parent_plat(dev); + ut_assert(plat != NULL); + + /* + * Check that it is not affected by the device being + * probed/removed + */ + plat->count++; + ut_asserteq(1, plat->count); + device_probe(dev); + device_remove(dev, DM_REMOVE_NORMAL); + + ut_asserteq_ptr(plat, dev_get_parent_plat(dev)); + ut_asserteq(1, plat->count); + ut_assertok(device_probe(dev)); + } + ut_asserteq(3, device_get_child_count(bus)); + + /* Removing the bus should also have no effect (it is still bound) */ + device_remove(bus, DM_REMOVE_NORMAL); + for (device_find_first_child(bus, &dev); + dev; + device_find_next_child(&dev)) { + /* Check that platform data is allocated */ + plat = dev_get_parent_plat(dev); + ut_assert(plat != NULL); + ut_asserteq(1, plat->count); + } + ut_asserteq(3, device_get_child_count(bus)); + + /* Unbind all the children */ + do { + device_find_first_child(bus, &dev); + if (dev) + device_unbind(dev); + } while (dev); + + /* Now the child plat should be removed and re-added */ + device_probe(bus); + for (device_find_first_child(bus, &dev); + dev; + device_find_next_child(&dev)) { + /* Check that platform data is allocated */ + plat = dev_get_parent_plat(dev); + ut_assert(plat != NULL); + ut_asserteq(0, plat->count); + } + ut_asserteq(3, device_get_child_count(bus)); + + return 0; +} + +/* Test that the bus can store platform data about each child */ +static int dm_test_bus_parent_plat(struct unit_test_state *uts) +{ + return test_bus_parent_plat(uts); +} +DM_TEST(dm_test_bus_parent_plat, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); + +/* As above but the size is controlled by the uclass */ +static int dm_test_bus_parent_plat_uclass(struct unit_test_state *uts) +{ + struct udevice *bus; + struct driver *drv; + int size; + int ret; + + /* Set the driver size to 0 so that the uclass size is used */ + ut_assertok(uclass_find_device(UCLASS_TEST_BUS, 0, &bus)); + drv = (struct driver *)bus->driver; + size = drv->per_child_plat_auto; +#ifdef CONFIG_SANDBOX + os_mprotect_allow(bus->uclass->uc_drv, sizeof(*bus->uclass->uc_drv)); + os_mprotect_allow(drv, sizeof(*drv)); +#endif + bus->uclass->uc_drv->per_child_plat_auto = size; + drv->per_child_plat_auto = 0; + ret = test_bus_parent_plat(uts); + if (ret) + return ret; + bus->uclass->uc_drv->per_child_plat_auto = 0; + drv->per_child_plat_auto = size; + + return 0; +} +DM_TEST(dm_test_bus_parent_plat_uclass, + UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); + +/* Test that the child post_bind method is called */ +static int dm_test_bus_child_post_bind(struct unit_test_state *uts) +{ + struct dm_test_parent_plat *plat; + struct udevice *bus, *dev; + + ut_assertok(uclass_get_device(UCLASS_TEST_BUS, 0, &bus)); + for (device_find_first_child(bus, &dev); + dev; + device_find_next_child(&dev)) { + /* Check that platform data is allocated */ + plat = dev_get_parent_plat(dev); + ut_assert(plat != NULL); + ut_asserteq(1, plat->bind_flag); + } + ut_asserteq(3, device_get_child_count(bus)); + + return 0; +} +DM_TEST(dm_test_bus_child_post_bind, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); + +/* Test that the child post_bind method is called */ +static int dm_test_bus_child_post_bind_uclass(struct unit_test_state *uts) +{ + struct dm_test_parent_plat *plat; + struct udevice *bus, *dev; + + ut_assertok(uclass_get_device(UCLASS_TEST_BUS, 0, &bus)); + for (device_find_first_child(bus, &dev); + dev; + device_find_next_child(&dev)) { + /* Check that platform data is allocated */ + plat = dev_get_parent_plat(dev); + ut_assert(plat != NULL); + ut_asserteq(2, plat->uclass_bind_flag); + } + ut_asserteq(3, device_get_child_count(bus)); + + return 0; +} +DM_TEST(dm_test_bus_child_post_bind_uclass, + UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); + +/* + * Test that the bus' uclass' child_pre_probe() is called before the + * device's probe() method + */ +static int dm_test_bus_child_pre_probe_uclass(struct unit_test_state *uts) +{ + struct udevice *bus, *dev; + + /* + * See testfdt_drv_probe() which effectively checks that the uclass + * flag is set before that method is called + */ + ut_assertok(uclass_get_device(UCLASS_TEST_BUS, 0, &bus)); + for (device_find_first_child(bus, &dev); + dev; + device_find_next_child(&dev)) { + struct dm_test_priv *priv = dev_get_priv(dev); + + /* Check that things happened in the right order */ + ut_asserteq_ptr(NULL, priv); + ut_assertok(device_probe(dev)); + + priv = dev_get_priv(dev); + ut_assert(priv != NULL); + ut_asserteq(1, priv->uclass_flag); + ut_asserteq(1, priv->uclass_total); + } + ut_asserteq(3, device_get_child_count(bus)); + + return 0; +} +DM_TEST(dm_test_bus_child_pre_probe_uclass, + UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); + +/* + * Test that the bus' uclass' child_post_probe() is called after the + * device's probe() method + */ +static int dm_test_bus_child_post_probe_uclass(struct unit_test_state *uts) +{ + struct udevice *bus, *dev; + + /* + * See testfdt_drv_probe() which effectively initializes that + * the uclass postp flag is set to a value + */ + ut_assertok(uclass_get_device(UCLASS_TEST_BUS, 0, &bus)); + for (device_find_first_child(bus, &dev); + dev; + device_find_next_child(&dev)) { + struct dm_test_priv *priv = dev_get_priv(dev); + + /* Check that things happened in the right order */ + ut_asserteq_ptr(NULL, priv); + ut_assertok(device_probe(dev)); + + priv = dev_get_priv(dev); + ut_assert(priv != NULL); + ut_asserteq(0, priv->uclass_postp); + } + ut_asserteq(3, device_get_child_count(bus)); + + return 0; +} +DM_TEST(dm_test_bus_child_post_probe_uclass, + UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); diff --git a/roms/u-boot/test/dm/button.c b/roms/u-boot/test/dm/button.c new file mode 100644 index 000000000..f8a7fab61 --- /dev/null +++ b/roms/u-boot/test/dm/button.c @@ -0,0 +1,120 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2020 Philippe Reynes <philippe.reynes@softathome.com> + * + * Based on led.c + */ + +#include <common.h> +#include <dm.h> +#include <adc.h> +#include <button.h> +#include <power/regulator.h> +#include <power/sandbox_pmic.h> +#include <asm/gpio.h> +#include <dm/test.h> +#include <test/ut.h> + +/* Base test of the button uclass */ +static int dm_test_button_base(struct unit_test_state *uts) +{ + struct udevice *dev; + + /* Get the top-level gpio buttons device */ + ut_assertok(uclass_get_device(UCLASS_BUTTON, 0, &dev)); + /* Get the 2 gpio buttons */ + ut_assertok(uclass_get_device(UCLASS_BUTTON, 1, &dev)); + ut_assertok(uclass_get_device(UCLASS_BUTTON, 2, &dev)); + + /* Get the top-level adc buttons device */ + ut_assertok(uclass_get_device(UCLASS_BUTTON, 3, &dev)); + /* Get the 3 adc buttons */ + ut_assertok(uclass_get_device(UCLASS_BUTTON, 4, &dev)); + ut_assertok(uclass_get_device(UCLASS_BUTTON, 5, &dev)); + ut_assertok(uclass_get_device(UCLASS_BUTTON, 6, &dev)); + + ut_asserteq(-ENODEV, uclass_get_device(UCLASS_BUTTON, 7, &dev)); + + return 0; +} +DM_TEST(dm_test_button_base, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); + +/* Test of the button uclass using the button_gpio driver */ +static int dm_test_button_gpio(struct unit_test_state *uts) +{ + const int offset = 3; + struct udevice *dev, *gpio; + + /* + * Check that we can manipulate an BUTTON. BUTTON 1 is connected to GPIO + * bank gpio_a, offset 3. + */ + ut_assertok(uclass_get_device(UCLASS_BUTTON, 1, &dev)); + ut_assertok(uclass_get_device(UCLASS_GPIO, 1, &gpio)); + + ut_asserteq(0, sandbox_gpio_set_value(gpio, offset, 0)); + ut_asserteq(0, sandbox_gpio_get_value(gpio, offset)); + ut_asserteq(BUTTON_OFF, button_get_state(dev)); + + ut_asserteq(0, sandbox_gpio_set_value(gpio, offset, 1)); + ut_asserteq(1, sandbox_gpio_get_value(gpio, offset)); + ut_asserteq(BUTTON_ON, button_get_state(dev)); + + return 0; +} +DM_TEST(dm_test_button_gpio, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); + +/* Test obtaining an BUTTON by label */ +static int dm_test_button_label(struct unit_test_state *uts) +{ + struct udevice *dev, *cmp; + + ut_assertok(button_get_by_label("button1", &dev)); + ut_asserteq(1, device_active(dev)); + ut_assertok(uclass_get_device(UCLASS_BUTTON, 1, &cmp)); + ut_asserteq_ptr(dev, cmp); + + ut_assertok(button_get_by_label("button2", &dev)); + ut_asserteq(1, device_active(dev)); + ut_assertok(uclass_get_device(UCLASS_BUTTON, 2, &cmp)); + ut_asserteq_ptr(dev, cmp); + + ut_asserteq(-ENODEV, button_get_by_label("nobutton", &dev)); + + return 0; +} +DM_TEST(dm_test_button_label, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); + +/* Test adc-keys driver */ +static int dm_test_button_keys_adc(struct unit_test_state *uts) +{ + struct udevice *supply; + struct udevice *dev; + int uV; + + ut_assertok(uclass_get_device_by_name(UCLASS_ADC, "adc@0", &dev)); + + ut_assertok(regulator_get_by_devname(SANDBOX_BUCK2_DEVNAME, &supply)); + ut_assertok(regulator_set_value(supply, SANDBOX_BUCK2_SET_UV)); + ut_asserteq(SANDBOX_BUCK2_SET_UV, regulator_get_value(supply)); + /* Update ADC plat and get new Vdd value */ + ut_assertok(adc_vdd_value(dev, &uV)); + ut_asserteq(SANDBOX_BUCK2_SET_UV, uV); + + /* + * sandbox-adc returns constant value on channel 3, is used by adc-keys: + * SANDBOX_ADC_CHANNEL3_DATA * SANDBOX_BUCK2_SET_UV / SANDBOX_ADC_DATA_MASK = + * 0x3000 * 3300000 / 0xffff = 618759uV + * This means that button3 and button4 are released and button5 + * is pressed. + */ + ut_assertok(button_get_by_label("button3", &dev)); + ut_asserteq(BUTTON_OFF, button_get_state(dev)); + ut_assertok(button_get_by_label("button4", &dev)); + ut_asserteq(BUTTON_OFF, button_get_state(dev)); + ut_assertok(button_get_by_label("button5", &dev)); + ut_asserteq(BUTTON_ON, button_get_state(dev)); + + return 0; +} +DM_TEST(dm_test_button_keys_adc, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); diff --git a/roms/u-boot/test/dm/cache.c b/roms/u-boot/test/dm/cache.c new file mode 100644 index 000000000..bbd8f98d0 --- /dev/null +++ b/roms/u-boot/test/dm/cache.c @@ -0,0 +1,22 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2019 Intel Corporation <www.intel.com> + */ + +#include <common.h> +#include <dm.h> +#include <dm/test.h> + +static int dm_test_reset(struct unit_test_state *uts) +{ + struct udevice *dev_cache; + struct cache_info; + + ut_assertok(uclass_get_device(UCLASS_CACHE, 0, &dev_cache)); + ut_assertok(cache_get_info(dev, &info)); + ut_assertok(cache_enable(dev)); + ut_assertok(cache_disable(dev)); + + return 0; +} +DM_TEST(dm_test_reset, UT_TESTF_SCAN_FDT); diff --git a/roms/u-boot/test/dm/clk.c b/roms/u-boot/test/dm/clk.c new file mode 100644 index 000000000..21997ed89 --- /dev/null +++ b/roms/u-boot/test/dm/clk.c @@ -0,0 +1,224 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2015 Google, Inc + */ + +#include <common.h> +#include <clk.h> +#include <dm.h> +#include <log.h> +#include <malloc.h> +#include <asm/clk.h> +#include <dm/test.h> +#include <dm/device-internal.h> +#include <linux/err.h> +#include <test/test.h> +#include <test/ut.h> + +/* Base test of the clk uclass */ +static int dm_test_clk_base(struct unit_test_state *uts) +{ + struct udevice *dev; + struct clk clk_method1; + struct clk clk_method2; + + /* Get the device using the clk device */ + ut_assertok(uclass_get_device_by_name(UCLASS_MISC, "clk-test", &dev)); + + /* Get the same clk port in 2 different ways and compare */ + ut_assertok(clk_get_by_index(dev, 1, &clk_method1)); + ut_assertok(clk_get_by_index_nodev(dev_ofnode(dev), 1, &clk_method2)); + ut_asserteq(clk_is_match(&clk_method1, &clk_method2), true); + ut_asserteq(clk_method1.id, clk_method2.id); + + return 0; +} + +DM_TEST(dm_test_clk_base, UT_TESTF_SCAN_FDT); + +static int dm_test_clk(struct unit_test_state *uts) +{ + struct udevice *dev_fixed, *dev_fixed_factor, *dev_clk, *dev_test; + ulong rate; + + ut_assertok(uclass_get_device_by_name(UCLASS_CLK, "clk-fixed", + &dev_fixed)); + + ut_assertok(uclass_get_device_by_name(UCLASS_CLK, "clk-fixed-factor", + &dev_fixed_factor)); + + ut_assertok(uclass_get_device_by_name(UCLASS_CLK, "clk-sbox", + &dev_clk)); + ut_asserteq(0, sandbox_clk_query_enable(dev_clk, SANDBOX_CLK_ID_SPI)); + ut_asserteq(0, sandbox_clk_query_enable(dev_clk, SANDBOX_CLK_ID_I2C)); + ut_asserteq(0, sandbox_clk_query_rate(dev_clk, SANDBOX_CLK_ID_SPI)); + ut_asserteq(0, sandbox_clk_query_rate(dev_clk, SANDBOX_CLK_ID_I2C)); + + ut_assertok(uclass_get_device_by_name(UCLASS_MISC, "clk-test", + &dev_test)); + ut_assertok(sandbox_clk_test_get(dev_test)); + ut_assertok(sandbox_clk_test_devm_get(dev_test)); + ut_assertok(sandbox_clk_test_valid(dev_test)); + + ut_asserteq(0, sandbox_clk_test_get_rate(dev_test, + SANDBOX_CLK_TEST_ID_DEVM_NULL)); + ut_asserteq(0, sandbox_clk_test_set_rate(dev_test, + SANDBOX_CLK_TEST_ID_DEVM_NULL, + 0)); + ut_asserteq(0, sandbox_clk_test_enable(dev_test, + SANDBOX_CLK_TEST_ID_DEVM_NULL)); + ut_asserteq(0, sandbox_clk_test_disable(dev_test, + SANDBOX_CLK_TEST_ID_DEVM_NULL)); + + ut_asserteq(1234, + sandbox_clk_test_get_rate(dev_test, + SANDBOX_CLK_TEST_ID_FIXED)); + ut_asserteq(0, sandbox_clk_test_get_rate(dev_test, + SANDBOX_CLK_TEST_ID_SPI)); + ut_asserteq(0, sandbox_clk_test_get_rate(dev_test, + SANDBOX_CLK_TEST_ID_I2C)); + ut_asserteq(321, sandbox_clk_test_get_rate(dev_test, + SANDBOX_CLK_TEST_ID_DEVM1)); + ut_asserteq(0, sandbox_clk_test_get_rate(dev_test, + SANDBOX_CLK_TEST_ID_DEVM2)); + + rate = sandbox_clk_test_set_rate(dev_test, SANDBOX_CLK_TEST_ID_FIXED, + 12345); + ut_assert(IS_ERR_VALUE(rate)); + rate = sandbox_clk_test_get_rate(dev_test, SANDBOX_CLK_TEST_ID_FIXED); + ut_asserteq(1234, rate); + + ut_asserteq(0, sandbox_clk_test_set_rate(dev_test, + SANDBOX_CLK_TEST_ID_SPI, + 1000)); + ut_asserteq(0, sandbox_clk_test_set_rate(dev_test, + SANDBOX_CLK_TEST_ID_I2C, + 2000)); + + ut_asserteq(1000, sandbox_clk_test_get_rate(dev_test, + SANDBOX_CLK_TEST_ID_SPI)); + ut_asserteq(2000, sandbox_clk_test_get_rate(dev_test, + SANDBOX_CLK_TEST_ID_I2C)); + + ut_asserteq(1000, sandbox_clk_test_set_rate(dev_test, + SANDBOX_CLK_TEST_ID_SPI, + 10000)); + ut_asserteq(2000, sandbox_clk_test_set_rate(dev_test, + SANDBOX_CLK_TEST_ID_I2C, + 20000)); + + rate = sandbox_clk_test_set_rate(dev_test, SANDBOX_CLK_TEST_ID_SPI, 0); + ut_assert(IS_ERR_VALUE(rate)); + rate = sandbox_clk_test_set_rate(dev_test, SANDBOX_CLK_TEST_ID_I2C, 0); + ut_assert(IS_ERR_VALUE(rate)); + + ut_asserteq(10000, sandbox_clk_test_get_rate(dev_test, + SANDBOX_CLK_TEST_ID_SPI)); + ut_asserteq(20000, sandbox_clk_test_get_rate(dev_test, + SANDBOX_CLK_TEST_ID_I2C)); + + ut_asserteq(5000, sandbox_clk_test_round_rate(dev_test, + SANDBOX_CLK_TEST_ID_SPI, + 5000)); + ut_asserteq(7000, sandbox_clk_test_round_rate(dev_test, + SANDBOX_CLK_TEST_ID_I2C, + 7000)); + + ut_asserteq(10000, sandbox_clk_test_get_rate(dev_test, + SANDBOX_CLK_TEST_ID_SPI)); + ut_asserteq(20000, sandbox_clk_test_get_rate(dev_test, + SANDBOX_CLK_TEST_ID_I2C)); + + rate = sandbox_clk_test_round_rate(dev_test, SANDBOX_CLK_TEST_ID_SPI, 0); + ut_assert(IS_ERR_VALUE(rate)); + rate = sandbox_clk_test_round_rate(dev_test, SANDBOX_CLK_TEST_ID_I2C, 0); + ut_assert(IS_ERR_VALUE(rate)); + + ut_asserteq(10000, sandbox_clk_test_get_rate(dev_test, + SANDBOX_CLK_TEST_ID_SPI)); + ut_asserteq(20000, sandbox_clk_test_get_rate(dev_test, + SANDBOX_CLK_TEST_ID_I2C)); + + ut_asserteq(0, sandbox_clk_query_enable(dev_clk, SANDBOX_CLK_ID_SPI)); + ut_asserteq(0, sandbox_clk_query_enable(dev_clk, SANDBOX_CLK_ID_I2C)); + ut_asserteq(10000, sandbox_clk_query_rate(dev_clk, SANDBOX_CLK_ID_SPI)); + ut_asserteq(20000, sandbox_clk_query_rate(dev_clk, SANDBOX_CLK_ID_I2C)); + + ut_assertok(sandbox_clk_test_enable(dev_test, SANDBOX_CLK_TEST_ID_SPI)); + ut_asserteq(1, sandbox_clk_query_enable(dev_clk, SANDBOX_CLK_ID_SPI)); + ut_asserteq(0, sandbox_clk_query_enable(dev_clk, SANDBOX_CLK_ID_I2C)); + + ut_assertok(sandbox_clk_test_enable(dev_test, SANDBOX_CLK_TEST_ID_I2C)); + ut_asserteq(1, sandbox_clk_query_enable(dev_clk, SANDBOX_CLK_ID_SPI)); + ut_asserteq(1, sandbox_clk_query_enable(dev_clk, SANDBOX_CLK_ID_I2C)); + + ut_assertok(sandbox_clk_test_disable(dev_test, + SANDBOX_CLK_TEST_ID_SPI)); + ut_asserteq(0, sandbox_clk_query_enable(dev_clk, SANDBOX_CLK_ID_SPI)); + ut_asserteq(1, sandbox_clk_query_enable(dev_clk, SANDBOX_CLK_ID_I2C)); + + ut_assertok(sandbox_clk_test_disable(dev_test, + SANDBOX_CLK_TEST_ID_I2C)); + ut_asserteq(0, sandbox_clk_query_enable(dev_clk, SANDBOX_CLK_ID_SPI)); + ut_asserteq(0, sandbox_clk_query_enable(dev_clk, SANDBOX_CLK_ID_I2C)); + + ut_asserteq(1, sandbox_clk_query_requested(dev_clk, + SANDBOX_CLK_ID_SPI)); + ut_asserteq(1, sandbox_clk_query_requested(dev_clk, + SANDBOX_CLK_ID_I2C)); + ut_asserteq(1, sandbox_clk_query_requested(dev_clk, + SANDBOX_CLK_ID_UART2)); + ut_assertok(sandbox_clk_test_free(dev_test)); + ut_asserteq(0, sandbox_clk_query_requested(dev_clk, + SANDBOX_CLK_ID_SPI)); + ut_asserteq(0, sandbox_clk_query_requested(dev_clk, + SANDBOX_CLK_ID_I2C)); + ut_asserteq(0, sandbox_clk_query_requested(dev_clk, + SANDBOX_CLK_ID_UART2)); + + ut_asserteq(1, sandbox_clk_query_requested(dev_clk, + SANDBOX_CLK_ID_UART1)); + ut_assertok(device_remove(dev_test, DM_REMOVE_NORMAL)); + ut_asserteq(0, sandbox_clk_query_requested(dev_clk, + SANDBOX_CLK_ID_UART1)); + return 0; +} +DM_TEST(dm_test_clk, UT_TESTF_SCAN_FDT); + +static int dm_test_clk_bulk(struct unit_test_state *uts) +{ + struct udevice *dev_clk, *dev_test; + + ut_assertok(uclass_get_device_by_name(UCLASS_CLK, "clk-sbox", + &dev_clk)); + ut_assertok(uclass_get_device_by_name(UCLASS_MISC, "clk-test", + &dev_test)); + ut_assertok(sandbox_clk_test_get_bulk(dev_test)); + + ut_asserteq(0, sandbox_clk_query_enable(dev_clk, SANDBOX_CLK_ID_SPI)); + ut_asserteq(0, sandbox_clk_query_enable(dev_clk, SANDBOX_CLK_ID_I2C)); + + /* Fixed clock does not support enable, thus should not fail */ + ut_assertok(sandbox_clk_test_enable_bulk(dev_test)); + ut_asserteq(1, sandbox_clk_query_enable(dev_clk, SANDBOX_CLK_ID_SPI)); + ut_asserteq(1, sandbox_clk_query_enable(dev_clk, SANDBOX_CLK_ID_I2C)); + + /* Fixed clock does not support disable, thus should not fail */ + ut_assertok(sandbox_clk_test_disable_bulk(dev_test)); + ut_asserteq(0, sandbox_clk_query_enable(dev_clk, SANDBOX_CLK_ID_SPI)); + ut_asserteq(0, sandbox_clk_query_enable(dev_clk, SANDBOX_CLK_ID_I2C)); + + /* Fixed clock does not support enable, thus should not fail */ + ut_assertok(sandbox_clk_test_enable_bulk(dev_test)); + ut_asserteq(1, sandbox_clk_query_enable(dev_clk, SANDBOX_CLK_ID_SPI)); + ut_asserteq(1, sandbox_clk_query_enable(dev_clk, SANDBOX_CLK_ID_I2C)); + + /* Fixed clock does not support disable, thus should not fail */ + ut_assertok(sandbox_clk_test_release_bulk(dev_test)); + ut_asserteq(0, sandbox_clk_query_enable(dev_clk, SANDBOX_CLK_ID_SPI)); + ut_asserteq(0, sandbox_clk_query_enable(dev_clk, SANDBOX_CLK_ID_I2C)); + ut_assertok(device_remove(dev_test, DM_REMOVE_NORMAL)); + + return 0; +} +DM_TEST(dm_test_clk_bulk, UT_TESTF_SCAN_FDT); diff --git a/roms/u-boot/test/dm/clk_ccf.c b/roms/u-boot/test/dm/clk_ccf.c new file mode 100644 index 000000000..e4ebb93cd --- /dev/null +++ b/roms/u-boot/test/dm/clk_ccf.c @@ -0,0 +1,195 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2019 + * Lukasz Majewski, DENX Software Engineering, lukma@denx.de + */ + +#include <common.h> +#include <clk.h> +#include <dm.h> +#include <asm/clk.h> +#include <dm/test.h> +#include <dm/uclass.h> +#include <linux/err.h> +#include <test/test.h> +#include <test/ut.h> +#include <sandbox-clk.h> + +/* Tests for Common Clock Framework driver */ +static int dm_test_clk_ccf(struct unit_test_state *uts) +{ + struct clk *clk, *pclk; + struct udevice *dev; + long long rate; + int ret; +#if CONFIG_IS_ENABLED(CLK_CCF) + const char *clkname; + int clkid, i; +#endif + + /* Get the device using the clk device */ + ut_assertok(uclass_get_device_by_name(UCLASS_CLK, "clk-ccf", &dev)); + + /* Test for clk_get_by_id() */ + ret = clk_get_by_id(SANDBOX_CLK_ECSPI_ROOT, &clk); + ut_assertok(ret); + ut_asserteq_str("ecspi_root", clk->dev->name); + ut_asserteq(CLK_SET_RATE_PARENT, clk->flags); + + /* Test for clk_get_parent_rate() */ + ret = clk_get_by_id(SANDBOX_CLK_ECSPI1, &clk); + ut_assertok(ret); + ut_asserteq_str("ecspi1", clk->dev->name); + ut_asserteq(CLK_SET_RATE_PARENT, clk->flags); + + rate = clk_get_parent_rate(clk); + ut_asserteq(rate, 20000000); + + /* test the gate of CCF */ + ret = clk_get_by_id(SANDBOX_CLK_ECSPI0, &clk); + ut_assertok(ret); + ut_asserteq_str("ecspi0", clk->dev->name); + ut_asserteq(CLK_SET_RATE_PARENT, clk->flags); + + rate = clk_get_parent_rate(clk); + ut_asserteq(rate, 20000000); + + /* Test the mux of CCF */ + ret = clk_get_by_id(SANDBOX_CLK_USDHC1_SEL, &clk); + ut_assertok(ret); + ut_asserteq_str("usdhc1_sel", clk->dev->name); + ut_asserteq(CLK_SET_RATE_NO_REPARENT, clk->flags); + + rate = clk_get_parent_rate(clk); + ut_asserteq(rate, 60000000); + + rate = clk_get_rate(clk); + ut_asserteq(rate, 60000000); + + ret = clk_get_by_id(SANDBOX_CLK_PLL3_80M, &pclk); + ut_assertok(ret); + + ret = clk_set_parent(clk, pclk); + ut_assertok(ret); + + rate = clk_get_rate(clk); + ut_asserteq(rate, 80000000); + + ret = clk_get_by_id(SANDBOX_CLK_USDHC2_SEL, &clk); + ut_assertok(ret); + ut_asserteq_str("usdhc2_sel", clk->dev->name); + ut_asserteq(CLK_SET_RATE_NO_REPARENT, clk->flags); + + rate = clk_get_parent_rate(clk); + ut_asserteq(rate, 80000000); + + pclk = clk_get_parent(clk); + ut_asserteq_str("pll3_80m", pclk->dev->name); + ut_asserteq(CLK_SET_RATE_PARENT, pclk->flags); + + rate = clk_get_rate(clk); + ut_asserteq(rate, 80000000); + + ret = clk_get_by_id(SANDBOX_CLK_PLL3_60M, &pclk); + ut_assertok(ret); + + ret = clk_set_parent(clk, pclk); + ut_assertok(ret); + + rate = clk_get_rate(clk); + ut_asserteq(rate, 60000000); + + /* Test the composite of CCF */ + ret = clk_get_by_id(SANDBOX_CLK_I2C, &clk); + ut_assertok(ret); + ut_asserteq_str("i2c", clk->dev->name); + ut_asserteq(CLK_SET_RATE_UNGATE, clk->flags); + + rate = clk_get_rate(clk); + ut_asserteq(rate, 60000000); + +#if CONFIG_IS_ENABLED(CLK_CCF) + /* Test clk tree enable/disable */ + ret = clk_get_by_id(SANDBOX_CLK_I2C_ROOT, &clk); + ut_assertok(ret); + ut_asserteq_str("i2c_root", clk->dev->name); + + ret = clk_enable(clk); + ut_assertok(ret); + + ret = sandbox_clk_enable_count(clk); + ut_asserteq(ret, 1); + + ret = clk_get_by_id(SANDBOX_CLK_I2C, &pclk); + ut_assertok(ret); + + ret = sandbox_clk_enable_count(pclk); + ut_asserteq(ret, 1); + + ret = clk_disable(clk); + ut_assertok(ret); + + ret = sandbox_clk_enable_count(clk); + ut_asserteq(ret, 0); + + ret = sandbox_clk_enable_count(pclk); + ut_asserteq(ret, 0); + + /* Test clock re-parenting. */ + ret = clk_get_by_id(SANDBOX_CLK_USDHC1_SEL, &clk); + ut_assertok(ret); + ut_asserteq_str("usdhc1_sel", clk->dev->name); + + pclk = clk_get_parent(clk); + ut_assertok_ptr(pclk); + if (!strcmp(pclk->dev->name, "pll3_60m")) { + clkname = "pll3_80m"; + clkid = SANDBOX_CLK_PLL3_80M; + } else { + clkname = "pll3_60m"; + clkid = SANDBOX_CLK_PLL3_60M; + } + + ret = clk_get_by_id(clkid, &pclk); + ut_assertok(ret); + ret = clk_set_parent(clk, pclk); + ut_assertok(ret); + pclk = clk_get_parent(clk); + ut_assertok_ptr(pclk); + ut_asserteq_str(clkname, pclk->dev->name); + + /* Test disabling critical clock. */ + ret = clk_get_by_id(SANDBOX_CLK_I2C_ROOT, &clk); + ut_assertok(ret); + ut_asserteq_str("i2c_root", clk->dev->name); + + /* Disable it, if any. */ + ret = sandbox_clk_enable_count(clk); + for (i = 0; i < ret; i++) { + ret = clk_disable(clk); + ut_assertok(ret); + } + + ret = sandbox_clk_enable_count(clk); + ut_asserteq(ret, 0); + + clk->flags = CLK_IS_CRITICAL; + ret = clk_enable(clk); + ut_assertok(ret); + + ret = clk_disable(clk); + ut_assertok(ret); + ret = sandbox_clk_enable_count(clk); + ut_asserteq(ret, 1); + clk->flags &= ~CLK_IS_CRITICAL; + + ret = clk_disable(clk); + ut_assertok(ret); + ret = sandbox_clk_enable_count(clk); + ut_asserteq(ret, 0); +#endif + + return 1; +} + +DM_TEST(dm_test_clk_ccf, UT_TESTF_SCAN_FDT); diff --git a/roms/u-boot/test/dm/core.c b/roms/u-boot/test/dm/core.c new file mode 100644 index 000000000..2210345dd --- /dev/null +++ b/roms/u-boot/test/dm/core.c @@ -0,0 +1,1202 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Tests for the core driver model code + * + * Copyright (c) 2013 Google, Inc + */ + +#include <common.h> +#include <errno.h> +#include <dm.h> +#include <fdtdec.h> +#include <log.h> +#include <malloc.h> +#include <asm/global_data.h> +#include <dm/device-internal.h> +#include <dm/root.h> +#include <dm/util.h> +#include <dm/test.h> +#include <dm/uclass-internal.h> +#include <test/test.h> +#include <test/ut.h> + +DECLARE_GLOBAL_DATA_PTR; + +enum { + TEST_INTVAL1 = 0, + TEST_INTVAL2 = 3, + TEST_INTVAL3 = 6, + TEST_INTVAL_MANUAL = 101112, + TEST_INTVAL_PRE_RELOC = 7, +}; + +static const struct dm_test_pdata test_pdata[] = { + { .ping_add = TEST_INTVAL1, }, + { .ping_add = TEST_INTVAL2, }, + { .ping_add = TEST_INTVAL3, }, +}; + +static const struct dm_test_pdata test_pdata_manual = { + .ping_add = TEST_INTVAL_MANUAL, +}; + +static const struct dm_test_pdata test_pdata_pre_reloc = { + .ping_add = TEST_INTVAL_PRE_RELOC, +}; + +U_BOOT_DRVINFO(dm_test_info1) = { + .name = "test_drv", + .plat = &test_pdata[0], +}; + +U_BOOT_DRVINFO(dm_test_info2) = { + .name = "test_drv", + .plat = &test_pdata[1], +}; + +U_BOOT_DRVINFO(dm_test_info3) = { + .name = "test_drv", + .plat = &test_pdata[2], +}; + +static struct driver_info driver_info_manual = { + .name = "test_manual_drv", + .plat = &test_pdata_manual, +}; + +static struct driver_info driver_info_pre_reloc = { + .name = "test_pre_reloc_drv", + .plat = &test_pdata_pre_reloc, +}; + +static struct driver_info driver_info_act_dma = { + .name = "test_act_dma_drv", +}; + +static struct driver_info driver_info_vital_clk = { + .name = "test_vital_clk_drv", +}; + +static struct driver_info driver_info_act_dma_vital_clk = { + .name = "test_act_dma_vital_clk_drv", +}; + +void dm_leak_check_start(struct unit_test_state *uts) +{ + uts->start = mallinfo(); + if (!uts->start.uordblks) + puts("Warning: Please add '#define DEBUG' to the top of common/dlmalloc.c\n"); +} + +int dm_leak_check_end(struct unit_test_state *uts) +{ + struct mallinfo end; + int id, diff; + + /* Don't delete the root class, since we started with that */ + for (id = UCLASS_ROOT + 1; id < UCLASS_COUNT; id++) { + struct uclass *uc; + + uc = uclass_find(id); + if (!uc) + continue; + ut_assertok(uclass_destroy(uc)); + } + + end = mallinfo(); + diff = end.uordblks - uts->start.uordblks; + if (diff > 0) + printf("Leak: lost %#xd bytes\n", diff); + else if (diff < 0) + printf("Leak: gained %#xd bytes\n", -diff); + ut_asserteq(uts->start.uordblks, end.uordblks); + + return 0; +} + +/* Test that binding with plat occurs correctly */ +static int dm_test_autobind(struct unit_test_state *uts) +{ + struct udevice *dev; + + /* + * We should have a single class (UCLASS_ROOT) and a single root + * device with no children. + */ + ut_assert(uts->root); + ut_asserteq(1, list_count_items(gd->uclass_root)); + ut_asserteq(0, list_count_items(&gd->dm_root->child_head)); + ut_asserteq(0, dm_testdrv_op_count[DM_TEST_OP_POST_BIND]); + + ut_assertok(dm_scan_plat(false)); + + /* We should have our test class now at least, plus more children */ + ut_assert(1 < list_count_items(gd->uclass_root)); + ut_assert(0 < list_count_items(&gd->dm_root->child_head)); + + /* Our 3 dm_test_infox children should be bound to the test uclass */ + ut_asserteq(3, dm_testdrv_op_count[DM_TEST_OP_POST_BIND]); + + /* No devices should be probed */ + list_for_each_entry(dev, &gd->dm_root->child_head, sibling_node) + ut_assert(!(dev_get_flags(dev) & DM_FLAG_ACTIVATED)); + + /* Our test driver should have been bound 3 times */ + ut_assert(dm_testdrv_op_count[DM_TEST_OP_BIND] == 3); + + return 0; +} +DM_TEST(dm_test_autobind, 0); + +/* Test that binding with uclass plat allocation occurs correctly */ +static int dm_test_autobind_uclass_pdata_alloc(struct unit_test_state *uts) +{ + struct dm_test_perdev_uc_pdata *uc_pdata; + struct udevice *dev; + struct uclass *uc; + + ut_assertok(uclass_get(UCLASS_TEST, &uc)); + ut_assert(uc); + + /** + * Test if test uclass driver requires allocation for the uclass + * platform data and then check the dev->uclass_plat pointer. + */ + ut_assert(uc->uc_drv->per_device_plat_auto); + + for (uclass_find_first_device(UCLASS_TEST, &dev); + dev; + uclass_find_next_device(&dev)) { + ut_assertnonnull(dev); + + uc_pdata = dev_get_uclass_plat(dev); + ut_assert(uc_pdata); + } + + return 0; +} +DM_TEST(dm_test_autobind_uclass_pdata_alloc, UT_TESTF_SCAN_PDATA); + +/* Test that binding with uclass plat setting occurs correctly */ +static int dm_test_autobind_uclass_pdata_valid(struct unit_test_state *uts) +{ + struct dm_test_perdev_uc_pdata *uc_pdata; + struct udevice *dev; + + /** + * In the test_postbind() method of test uclass driver, the uclass + * platform data should be set to three test int values - test it. + */ + for (uclass_find_first_device(UCLASS_TEST, &dev); + dev; + uclass_find_next_device(&dev)) { + ut_assertnonnull(dev); + + uc_pdata = dev_get_uclass_plat(dev); + ut_assert(uc_pdata); + ut_assert(uc_pdata->intval1 == TEST_UC_PDATA_INTVAL1); + ut_assert(uc_pdata->intval2 == TEST_UC_PDATA_INTVAL2); + ut_assert(uc_pdata->intval3 == TEST_UC_PDATA_INTVAL3); + } + + return 0; +} +DM_TEST(dm_test_autobind_uclass_pdata_valid, UT_TESTF_SCAN_PDATA); + +/* Test that autoprobe finds all the expected devices */ +static int dm_test_autoprobe(struct unit_test_state *uts) +{ + int expected_base_add; + struct udevice *dev; + struct uclass *uc; + int i; + + ut_assertok(uclass_get(UCLASS_TEST, &uc)); + ut_assert(uc); + + ut_asserteq(1, dm_testdrv_op_count[DM_TEST_OP_INIT]); + ut_asserteq(0, dm_testdrv_op_count[DM_TEST_OP_PRE_PROBE]); + ut_asserteq(0, dm_testdrv_op_count[DM_TEST_OP_POST_PROBE]); + + /* The root device should not be activated until needed */ + ut_assert(dev_get_flags(uts->root) & DM_FLAG_ACTIVATED); + + /* + * We should be able to find the three test devices, and they should + * all be activated as they are used (lazy activation, required by + * U-Boot) + */ + for (i = 0; i < 3; i++) { + ut_assertok(uclass_find_device(UCLASS_TEST, i, &dev)); + ut_assert(dev); + ut_assertf(!(dev_get_flags(dev) & DM_FLAG_ACTIVATED), + "Driver %d/%s already activated", i, dev->name); + + /* This should activate it */ + ut_assertok(uclass_get_device(UCLASS_TEST, i, &dev)); + ut_assert(dev); + ut_assert(dev_get_flags(dev) & DM_FLAG_ACTIVATED); + + /* Activating a device should activate the root device */ + if (!i) + ut_assert(dev_get_flags(uts->root) & DM_FLAG_ACTIVATED); + } + + /* + * Our 3 dm_test_info children should be passed to pre_probe and + * post_probe + */ + ut_asserteq(3, dm_testdrv_op_count[DM_TEST_OP_POST_PROBE]); + ut_asserteq(3, dm_testdrv_op_count[DM_TEST_OP_PRE_PROBE]); + + /* Also we can check the per-device data */ + expected_base_add = 0; + for (i = 0; i < 3; i++) { + struct dm_test_uclass_perdev_priv *priv; + struct dm_test_pdata *pdata; + + ut_assertok(uclass_find_device(UCLASS_TEST, i, &dev)); + ut_assert(dev); + + priv = dev_get_uclass_priv(dev); + ut_assert(priv); + ut_asserteq(expected_base_add, priv->base_add); + + pdata = dev_get_plat(dev); + expected_base_add += pdata->ping_add; + } + + return 0; +} +DM_TEST(dm_test_autoprobe, UT_TESTF_SCAN_PDATA); + +/* Check that we see the correct plat in each device */ +static int dm_test_plat(struct unit_test_state *uts) +{ + const struct dm_test_pdata *pdata; + struct udevice *dev; + int i; + + for (i = 0; i < 3; i++) { + ut_assertok(uclass_find_device(UCLASS_TEST, i, &dev)); + ut_assert(dev); + pdata = dev_get_plat(dev); + ut_assert(pdata->ping_add == test_pdata[i].ping_add); + } + + return 0; +} +DM_TEST(dm_test_plat, UT_TESTF_SCAN_PDATA); + +/* Test that we can bind, probe, remove, unbind a driver */ +static int dm_test_lifecycle(struct unit_test_state *uts) +{ + int op_count[DM_TEST_OP_COUNT]; + struct udevice *dev, *test_dev; + int pingret; + int ret; + + memcpy(op_count, dm_testdrv_op_count, sizeof(op_count)); + + ut_assertok(device_bind_by_name(uts->root, false, &driver_info_manual, + &dev)); + ut_assert(dev); + ut_assert(dm_testdrv_op_count[DM_TEST_OP_BIND] + == op_count[DM_TEST_OP_BIND] + 1); + ut_assert(!dev_get_priv(dev)); + + /* Probe the device - it should fail allocating private data */ + uts->force_fail_alloc = 1; + ret = device_probe(dev); + ut_assert(ret == -ENOMEM); + ut_assert(dm_testdrv_op_count[DM_TEST_OP_PROBE] + == op_count[DM_TEST_OP_PROBE] + 1); + ut_assert(!dev_get_priv(dev)); + + /* Try again without the alloc failure */ + uts->force_fail_alloc = 0; + ut_assertok(device_probe(dev)); + ut_assert(dm_testdrv_op_count[DM_TEST_OP_PROBE] + == op_count[DM_TEST_OP_PROBE] + 2); + ut_assert(dev_get_priv(dev)); + + /* This should be device 3 in the uclass */ + ut_assertok(uclass_find_device(UCLASS_TEST, 3, &test_dev)); + ut_assert(dev == test_dev); + + /* Try ping */ + ut_assertok(test_ping(dev, 100, &pingret)); + ut_assert(pingret == 102); + + /* Now remove device 3 */ + ut_asserteq(0, dm_testdrv_op_count[DM_TEST_OP_PRE_REMOVE]); + ut_assertok(device_remove(dev, DM_REMOVE_NORMAL)); + ut_asserteq(1, dm_testdrv_op_count[DM_TEST_OP_PRE_REMOVE]); + + ut_asserteq(0, dm_testdrv_op_count[DM_TEST_OP_UNBIND]); + ut_asserteq(0, dm_testdrv_op_count[DM_TEST_OP_PRE_UNBIND]); + ut_assertok(device_unbind(dev)); + ut_asserteq(1, dm_testdrv_op_count[DM_TEST_OP_UNBIND]); + ut_asserteq(1, dm_testdrv_op_count[DM_TEST_OP_PRE_UNBIND]); + + return 0; +} +DM_TEST(dm_test_lifecycle, UT_TESTF_SCAN_PDATA | UT_TESTF_PROBE_TEST); + +/* Test that we can bind/unbind and the lists update correctly */ +static int dm_test_ordering(struct unit_test_state *uts) +{ + struct udevice *dev, *dev_penultimate, *dev_last, *test_dev; + int pingret; + + ut_assertok(device_bind_by_name(uts->root, false, &driver_info_manual, + &dev)); + ut_assert(dev); + + /* Bind two new devices (numbers 4 and 5) */ + ut_assertok(device_bind_by_name(uts->root, false, &driver_info_manual, + &dev_penultimate)); + ut_assert(dev_penultimate); + ut_assertok(device_bind_by_name(uts->root, false, &driver_info_manual, + &dev_last)); + ut_assert(dev_last); + + /* Now remove device 3 */ + ut_assertok(device_remove(dev, DM_REMOVE_NORMAL)); + ut_assertok(device_unbind(dev)); + + /* The device numbering should have shifted down one */ + ut_assertok(uclass_find_device(UCLASS_TEST, 3, &test_dev)); + ut_assert(dev_penultimate == test_dev); + ut_assertok(uclass_find_device(UCLASS_TEST, 4, &test_dev)); + ut_assert(dev_last == test_dev); + + /* Add back the original device 3, now in position 5 */ + ut_assertok(device_bind_by_name(uts->root, false, &driver_info_manual, + &dev)); + ut_assert(dev); + + /* Try ping */ + ut_assertok(test_ping(dev, 100, &pingret)); + ut_assert(pingret == 102); + + /* Remove 3 and 4 */ + ut_assertok(device_remove(dev_penultimate, DM_REMOVE_NORMAL)); + ut_assertok(device_unbind(dev_penultimate)); + ut_assertok(device_remove(dev_last, DM_REMOVE_NORMAL)); + ut_assertok(device_unbind(dev_last)); + + /* Our device should now be in position 3 */ + ut_assertok(uclass_find_device(UCLASS_TEST, 3, &test_dev)); + ut_assert(dev == test_dev); + + /* Now remove device 3 */ + ut_assertok(device_remove(dev, DM_REMOVE_NORMAL)); + ut_assertok(device_unbind(dev)); + + return 0; +} +DM_TEST(dm_test_ordering, UT_TESTF_SCAN_PDATA); + +/* Check that we can perform operations on a device (do a ping) */ +int dm_check_operations(struct unit_test_state *uts, struct udevice *dev, + uint32_t base, struct dm_test_priv *priv) +{ + int expected; + int pingret; + + /* Getting the child device should allocate plat / priv */ + ut_assertok(testfdt_ping(dev, 10, &pingret)); + ut_assert(dev_get_priv(dev)); + ut_assert(dev_get_plat(dev)); + + expected = 10 + base; + ut_asserteq(expected, pingret); + + /* Do another ping */ + ut_assertok(testfdt_ping(dev, 20, &pingret)); + expected = 20 + base; + ut_asserteq(expected, pingret); + + /* Now check the ping_total */ + priv = dev_get_priv(dev); + ut_asserteq(DM_TEST_START_TOTAL + 10 + 20 + base * 2, + priv->ping_total); + + return 0; +} + +/* Check that we can perform operations on devices */ +static int dm_test_operations(struct unit_test_state *uts) +{ + struct udevice *dev; + int i; + + /* + * Now check that the ping adds are what we expect. This is using the + * ping-add property in each node. + */ + for (i = 0; i < ARRAY_SIZE(test_pdata); i++) { + uint32_t base; + + ut_assertok(uclass_get_device(UCLASS_TEST, i, &dev)); + + /* + * Get the 'reg' property, which tells us what the ping add + * should be. We don't use the plat because we want + * to test the code that sets that up (testfdt_drv_probe()). + */ + base = test_pdata[i].ping_add; + debug("dev=%d, base=%d\n", i, base); + + ut_assert(!dm_check_operations(uts, dev, base, dev_get_priv(dev))); + } + + return 0; +} +DM_TEST(dm_test_operations, UT_TESTF_SCAN_PDATA); + +/* Remove all drivers and check that things work */ +static int dm_test_remove(struct unit_test_state *uts) +{ + struct udevice *dev; + int i; + + for (i = 0; i < 3; i++) { + ut_assertok(uclass_find_device(UCLASS_TEST, i, &dev)); + ut_assert(dev); + ut_assertf(dev_get_flags(dev) & DM_FLAG_ACTIVATED, + "Driver %d/%s not activated", i, dev->name); + ut_assertok(device_remove(dev, DM_REMOVE_NORMAL)); + ut_assertf(!(dev_get_flags(dev) & DM_FLAG_ACTIVATED), + "Driver %d/%s should have deactivated", i, + dev->name); + ut_assert(!dev_get_priv(dev)); + } + + return 0; +} +DM_TEST(dm_test_remove, UT_TESTF_SCAN_PDATA | UT_TESTF_PROBE_TEST); + +/* Remove and recreate everything, check for memory leaks */ +static int dm_test_leak(struct unit_test_state *uts) +{ + int i; + + for (i = 0; i < 2; i++) { + struct udevice *dev; + int ret; + int id; + + dm_leak_check_start(uts); + + ut_assertok(dm_scan_plat(false)); + ut_assertok(dm_scan_fdt(false)); + + /* Scanning the uclass is enough to probe all the devices */ + for (id = UCLASS_ROOT; id < UCLASS_COUNT; id++) { + for (ret = uclass_first_device(UCLASS_TEST, &dev); + dev; + ret = uclass_next_device(&dev)) + ; + ut_assertok(ret); + } + + ut_assertok(dm_leak_check_end(uts)); + } + + return 0; +} +DM_TEST(dm_test_leak, 0); + +/* Test uclass init/destroy methods */ +static int dm_test_uclass(struct unit_test_state *uts) +{ + struct uclass *uc; + + ut_assertok(uclass_get(UCLASS_TEST, &uc)); + ut_asserteq(1, dm_testdrv_op_count[DM_TEST_OP_INIT]); + ut_asserteq(0, dm_testdrv_op_count[DM_TEST_OP_DESTROY]); + ut_assert(uclass_get_priv(uc)); + + ut_assertok(uclass_destroy(uc)); + ut_asserteq(1, dm_testdrv_op_count[DM_TEST_OP_INIT]); + ut_asserteq(1, dm_testdrv_op_count[DM_TEST_OP_DESTROY]); + + return 0; +} +DM_TEST(dm_test_uclass, 0); + +/** + * create_children() - Create children of a parent node + * + * @dms: Test system state + * @parent: Parent device + * @count: Number of children to create + * @key: Key value to put in first child. Subsequence children + * receive an incrementing value + * @child: If not NULL, then the child device pointers are written into + * this array. + * @return 0 if OK, -ve on error + */ +static int create_children(struct unit_test_state *uts, struct udevice *parent, + int count, int key, struct udevice *child[]) +{ + struct udevice *dev; + int i; + + for (i = 0; i < count; i++) { + struct dm_test_pdata *pdata; + + ut_assertok(device_bind_by_name(parent, false, + &driver_info_manual, &dev)); + pdata = calloc(1, sizeof(*pdata)); + pdata->ping_add = key + i; + dev_set_plat(dev, pdata); + if (child) + child[i] = dev; + } + + return 0; +} + +#define NODE_COUNT 10 + +static int dm_test_children(struct unit_test_state *uts) +{ + struct udevice *top[NODE_COUNT]; + struct udevice *child[NODE_COUNT]; + struct udevice *grandchild[NODE_COUNT]; + struct udevice *dev; + int total; + int ret; + int i; + + /* We don't care about the numbering for this test */ + uts->skip_post_probe = 1; + + ut_assert(NODE_COUNT > 5); + + /* First create 10 top-level children */ + ut_assertok(create_children(uts, uts->root, NODE_COUNT, 0, top)); + + /* Now a few have their own children */ + ut_assertok(create_children(uts, top[2], NODE_COUNT, 2, NULL)); + ut_assertok(create_children(uts, top[5], NODE_COUNT, 5, child)); + + /* And grandchildren */ + for (i = 0; i < NODE_COUNT; i++) + ut_assertok(create_children(uts, child[i], NODE_COUNT, 50 * i, + i == 2 ? grandchild : NULL)); + + /* Check total number of devices */ + total = NODE_COUNT * (3 + NODE_COUNT); + ut_asserteq(total, dm_testdrv_op_count[DM_TEST_OP_BIND]); + + /* Try probing one of the grandchildren */ + ut_assertok(uclass_get_device(UCLASS_TEST, + NODE_COUNT * 3 + 2 * NODE_COUNT, &dev)); + ut_asserteq_ptr(grandchild[0], dev); + + /* + * This should have probed the child and top node also, for a total + * of 3 nodes. + */ + ut_asserteq(3, dm_testdrv_op_count[DM_TEST_OP_PROBE]); + + /* Probe the other grandchildren */ + for (i = 1; i < NODE_COUNT; i++) + ut_assertok(device_probe(grandchild[i])); + + ut_asserteq(2 + NODE_COUNT, dm_testdrv_op_count[DM_TEST_OP_PROBE]); + + /* Probe everything */ + for (ret = uclass_first_device(UCLASS_TEST, &dev); + dev; + ret = uclass_next_device(&dev)) + ; + ut_assertok(ret); + + ut_asserteq(total, dm_testdrv_op_count[DM_TEST_OP_PROBE]); + + /* Remove a top-level child and check that the children are removed */ + ut_assertok(device_remove(top[2], DM_REMOVE_NORMAL)); + ut_asserteq(NODE_COUNT + 1, dm_testdrv_op_count[DM_TEST_OP_REMOVE]); + dm_testdrv_op_count[DM_TEST_OP_REMOVE] = 0; + + /* Try one with grandchildren */ + ut_assertok(uclass_get_device(UCLASS_TEST, 5, &dev)); + ut_asserteq_ptr(dev, top[5]); + ut_assertok(device_remove(dev, DM_REMOVE_NORMAL)); + ut_asserteq(1 + NODE_COUNT * (1 + NODE_COUNT), + dm_testdrv_op_count[DM_TEST_OP_REMOVE]); + + /* Try the same with unbind */ + ut_assertok(device_unbind(top[2])); + ut_asserteq(NODE_COUNT + 1, dm_testdrv_op_count[DM_TEST_OP_UNBIND]); + dm_testdrv_op_count[DM_TEST_OP_UNBIND] = 0; + + /* Try one with grandchildren */ + ut_assertok(uclass_get_device(UCLASS_TEST, 5, &dev)); + ut_asserteq_ptr(dev, top[6]); + ut_assertok(device_unbind(top[5])); + ut_asserteq(1 + NODE_COUNT * (1 + NODE_COUNT), + dm_testdrv_op_count[DM_TEST_OP_UNBIND]); + + return 0; +} +DM_TEST(dm_test_children, 0); + +static int dm_test_device_reparent(struct unit_test_state *uts) +{ + struct udevice *top[NODE_COUNT]; + struct udevice *child[NODE_COUNT]; + struct udevice *grandchild[NODE_COUNT]; + struct udevice *dev; + int total; + int ret; + int i; + + /* We don't care about the numbering for this test */ + uts->skip_post_probe = 1; + + ut_assert(NODE_COUNT > 5); + + /* First create 10 top-level children */ + ut_assertok(create_children(uts, uts->root, NODE_COUNT, 0, top)); + + /* Now a few have their own children */ + ut_assertok(create_children(uts, top[2], NODE_COUNT, 2, NULL)); + ut_assertok(create_children(uts, top[5], NODE_COUNT, 5, child)); + + /* And grandchildren */ + for (i = 0; i < NODE_COUNT; i++) + ut_assertok(create_children(uts, child[i], NODE_COUNT, 50 * i, + i == 2 ? grandchild : NULL)); + + /* Check total number of devices */ + total = NODE_COUNT * (3 + NODE_COUNT); + ut_asserteq(total, dm_testdrv_op_count[DM_TEST_OP_BIND]); + + /* Probe everything */ + for (i = 0; i < total; i++) + ut_assertok(uclass_get_device(UCLASS_TEST, i, &dev)); + + /* Re-parent top-level children with no grandchildren. */ + ut_assertok(device_reparent(top[3], top[0])); + /* try to get devices */ + for (ret = uclass_find_first_device(UCLASS_TEST, &dev); + dev; + ret = uclass_find_next_device(&dev)) { + ut_assert(!ret); + ut_assertnonnull(dev); + } + + ut_assertok(device_reparent(top[4], top[0])); + /* try to get devices */ + for (ret = uclass_find_first_device(UCLASS_TEST, &dev); + dev; + ret = uclass_find_next_device(&dev)) { + ut_assert(!ret); + ut_assertnonnull(dev); + } + + /* Re-parent top-level children with grandchildren. */ + ut_assertok(device_reparent(top[2], top[0])); + /* try to get devices */ + for (ret = uclass_find_first_device(UCLASS_TEST, &dev); + dev; + ret = uclass_find_next_device(&dev)) { + ut_assert(!ret); + ut_assertnonnull(dev); + } + + ut_assertok(device_reparent(top[5], top[2])); + /* try to get devices */ + for (ret = uclass_find_first_device(UCLASS_TEST, &dev); + dev; + ret = uclass_find_next_device(&dev)) { + ut_assert(!ret); + ut_assertnonnull(dev); + } + + /* Re-parent grandchildren. */ + ut_assertok(device_reparent(grandchild[0], top[1])); + /* try to get devices */ + for (ret = uclass_find_first_device(UCLASS_TEST, &dev); + dev; + ret = uclass_find_next_device(&dev)) { + ut_assert(!ret); + ut_assertnonnull(dev); + } + + ut_assertok(device_reparent(grandchild[1], top[1])); + /* try to get devices */ + for (ret = uclass_find_first_device(UCLASS_TEST, &dev); + dev; + ret = uclass_find_next_device(&dev)) { + ut_assert(!ret); + ut_assertnonnull(dev); + } + + /* Remove re-pareneted devices. */ + ut_assertok(device_remove(top[3], DM_REMOVE_NORMAL)); + /* try to get devices */ + for (ret = uclass_find_first_device(UCLASS_TEST, &dev); + dev; + ret = uclass_find_next_device(&dev)) { + ut_assert(!ret); + ut_assertnonnull(dev); + } + + ut_assertok(device_remove(top[4], DM_REMOVE_NORMAL)); + /* try to get devices */ + for (ret = uclass_find_first_device(UCLASS_TEST, &dev); + dev; + ret = uclass_find_next_device(&dev)) { + ut_assert(!ret); + ut_assertnonnull(dev); + } + + ut_assertok(device_remove(top[5], DM_REMOVE_NORMAL)); + /* try to get devices */ + for (ret = uclass_find_first_device(UCLASS_TEST, &dev); + dev; + ret = uclass_find_next_device(&dev)) { + ut_assert(!ret); + ut_assertnonnull(dev); + } + + ut_assertok(device_remove(top[2], DM_REMOVE_NORMAL)); + for (ret = uclass_find_first_device(UCLASS_TEST, &dev); + dev; + ret = uclass_find_next_device(&dev)) { + ut_assert(!ret); + ut_assertnonnull(dev); + } + + ut_assertok(device_remove(grandchild[0], DM_REMOVE_NORMAL)); + /* try to get devices */ + for (ret = uclass_find_first_device(UCLASS_TEST, &dev); + dev; + ret = uclass_find_next_device(&dev)) { + ut_assert(!ret); + ut_assertnonnull(dev); + } + + ut_assertok(device_remove(grandchild[1], DM_REMOVE_NORMAL)); + /* try to get devices */ + for (ret = uclass_find_first_device(UCLASS_TEST, &dev); + dev; + ret = uclass_find_next_device(&dev)) { + ut_assert(!ret); + ut_assertnonnull(dev); + } + + /* Try the same with unbind */ + ut_assertok(device_unbind(top[3])); + ut_assertok(device_unbind(top[4])); + ut_assertok(device_unbind(top[5])); + ut_assertok(device_unbind(top[2])); + + ut_assertok(device_unbind(grandchild[0])); + ut_assertok(device_unbind(grandchild[1])); + + return 0; +} +DM_TEST(dm_test_device_reparent, 0); + +/* Test that pre-relocation devices work as expected */ +static int dm_test_pre_reloc(struct unit_test_state *uts) +{ + struct udevice *dev; + + /* The normal driver should refuse to bind before relocation */ + ut_asserteq(-EPERM, device_bind_by_name(uts->root, true, + &driver_info_manual, &dev)); + + /* But this one is marked pre-reloc */ + ut_assertok(device_bind_by_name(uts->root, true, + &driver_info_pre_reloc, &dev)); + + return 0; +} +DM_TEST(dm_test_pre_reloc, 0); + +/* + * Test that removal of devices, either via the "normal" device_remove() + * API or via the device driver selective flag works as expected + */ +static int dm_test_remove_active_dma(struct unit_test_state *uts) +{ + struct udevice *dev; + + ut_assertok(device_bind_by_name(uts->root, false, &driver_info_act_dma, + &dev)); + ut_assert(dev); + + /* Probe the device */ + ut_assertok(device_probe(dev)); + + /* Test if device is active right now */ + ut_asserteq(true, device_active(dev)); + + /* Remove the device via selective remove flag */ + dm_remove_devices_flags(DM_REMOVE_ACTIVE_ALL); + + /* Test if device is inactive right now */ + ut_asserteq(false, device_active(dev)); + + /* Probe the device again */ + ut_assertok(device_probe(dev)); + + /* Test if device is active right now */ + ut_asserteq(true, device_active(dev)); + + /* Remove the device via "normal" remove API */ + ut_assertok(device_remove(dev, DM_REMOVE_NORMAL)); + + /* Test if device is inactive right now */ + ut_asserteq(false, device_active(dev)); + + /* + * Test if a device without the active DMA flags is not removed upon + * the active DMA remove call + */ + ut_assertok(device_unbind(dev)); + ut_assertok(device_bind_by_name(uts->root, false, &driver_info_manual, + &dev)); + ut_assert(dev); + + /* Probe the device */ + ut_assertok(device_probe(dev)); + + /* Test if device is active right now */ + ut_asserteq(true, device_active(dev)); + + /* Remove the device via selective remove flag */ + dm_remove_devices_flags(DM_REMOVE_ACTIVE_ALL); + + /* Test if device is still active right now */ + ut_asserteq(true, device_active(dev)); + + return 0; +} +DM_TEST(dm_test_remove_active_dma, 0); + +/* Test removal of 'vital' devices */ +static int dm_test_remove_vital(struct unit_test_state *uts) +{ + struct udevice *normal, *dma, *vital, *dma_vital; + + /* Skip the behaviour in test_post_probe() */ + uts->skip_post_probe = 1; + + ut_assertok(device_bind_by_name(uts->root, false, &driver_info_manual, + &normal)); + ut_assertnonnull(normal); + + ut_assertok(device_bind_by_name(uts->root, false, &driver_info_act_dma, + &dma)); + ut_assertnonnull(dma); + + ut_assertok(device_bind_by_name(uts->root, false, + &driver_info_vital_clk, &vital)); + ut_assertnonnull(vital); + + ut_assertok(device_bind_by_name(uts->root, false, + &driver_info_act_dma_vital_clk, + &dma_vital)); + ut_assertnonnull(dma_vital); + + /* Probe the devices */ + ut_assertok(device_probe(normal)); + ut_assertok(device_probe(dma)); + ut_assertok(device_probe(vital)); + ut_assertok(device_probe(dma_vital)); + + /* Check that devices are active right now */ + ut_asserteq(true, device_active(normal)); + ut_asserteq(true, device_active(dma)); + ut_asserteq(true, device_active(vital)); + ut_asserteq(true, device_active(dma_vital)); + + /* Remove active devices via selective remove flag */ + dm_remove_devices_flags(DM_REMOVE_NON_VITAL | DM_REMOVE_ACTIVE_ALL); + + /* + * Check that this only has an effect on the dma device, since two + * devices are vital and the third does not have active DMA + */ + ut_asserteq(true, device_active(normal)); + ut_asserteq(false, device_active(dma)); + ut_asserteq(true, device_active(vital)); + ut_asserteq(true, device_active(dma_vital)); + + /* Remove active devices via selective remove flag */ + ut_assertok(device_probe(dma)); + dm_remove_devices_flags(DM_REMOVE_ACTIVE_ALL); + + /* This should have affected both active-dma devices */ + ut_asserteq(true, device_active(normal)); + ut_asserteq(false, device_active(dma)); + ut_asserteq(true, device_active(vital)); + ut_asserteq(false, device_active(dma_vital)); + + /* Remove non-vital devices */ + ut_assertok(device_probe(dma)); + ut_assertok(device_probe(dma_vital)); + dm_remove_devices_flags(DM_REMOVE_NON_VITAL); + + /* This should have affected only non-vital devices */ + ut_asserteq(false, device_active(normal)); + ut_asserteq(false, device_active(dma)); + ut_asserteq(true, device_active(vital)); + ut_asserteq(true, device_active(dma_vital)); + + /* Remove vital devices via normal remove flag */ + ut_assertok(device_probe(normal)); + ut_assertok(device_probe(dma)); + dm_remove_devices_flags(DM_REMOVE_NORMAL); + + /* Check that all devices are inactive right now */ + ut_asserteq(false, device_active(normal)); + ut_asserteq(false, device_active(dma)); + ut_asserteq(false, device_active(vital)); + ut_asserteq(false, device_active(dma_vital)); + + return 0; +} +DM_TEST(dm_test_remove_vital, 0); + +static int dm_test_uclass_before_ready(struct unit_test_state *uts) +{ + struct uclass *uc; + + ut_assertok(uclass_get(UCLASS_TEST, &uc)); + + gd->dm_root = NULL; + gd->dm_root_f = NULL; + memset(&gd->uclass_root, '\0', sizeof(gd->uclass_root)); + + ut_asserteq_ptr(NULL, uclass_find(UCLASS_TEST)); + + return 0; +} +DM_TEST(dm_test_uclass_before_ready, 0); + +static int dm_test_uclass_devices_find(struct unit_test_state *uts) +{ + struct udevice *dev; + int ret; + + for (ret = uclass_find_first_device(UCLASS_TEST, &dev); + dev; + ret = uclass_find_next_device(&dev)) { + ut_assert(!ret); + ut_assertnonnull(dev); + } + + ut_assertok(uclass_find_first_device(UCLASS_TEST_DUMMY, &dev)); + ut_assertnull(dev); + + return 0; +} +DM_TEST(dm_test_uclass_devices_find, UT_TESTF_SCAN_PDATA); + +static int dm_test_uclass_devices_find_by_name(struct unit_test_state *uts) +{ + struct udevice *finddev; + struct udevice *testdev; + int findret, ret; + + /* + * For each test device found in fdt like: "a-test", "b-test", etc., + * use its name and try to find it by uclass_find_device_by_name(). + * Then, on success check if: + * - current 'testdev' name is equal to the returned 'finddev' name + * - current 'testdev' pointer is equal to the returned 'finddev' + * + * We assume that, each uclass's device name is unique, so if not, then + * this will fail on checking condition: testdev == finddev, since the + * uclass_find_device_by_name(), returns the first device by given name. + */ + for (ret = uclass_find_first_device(UCLASS_TEST_FDT, &testdev); + testdev; + ret = uclass_find_next_device(&testdev)) { + ut_assertok(ret); + ut_assertnonnull(testdev); + + findret = uclass_find_device_by_name(UCLASS_TEST_FDT, + testdev->name, + &finddev); + + ut_assertok(findret); + ut_assert(testdev); + ut_asserteq_str(testdev->name, finddev->name); + ut_asserteq_ptr(testdev, finddev); + } + + return 0; +} +DM_TEST(dm_test_uclass_devices_find_by_name, UT_TESTF_SCAN_FDT); + +static int dm_test_uclass_devices_get(struct unit_test_state *uts) +{ + struct udevice *dev; + int ret; + + for (ret = uclass_first_device(UCLASS_TEST, &dev); + dev; + ret = uclass_next_device(&dev)) { + ut_assert(!ret); + ut_assert(dev); + ut_assert(device_active(dev)); + } + + return 0; +} +DM_TEST(dm_test_uclass_devices_get, UT_TESTF_SCAN_PDATA); + +static int dm_test_uclass_devices_get_by_name(struct unit_test_state *uts) +{ + struct udevice *finddev; + struct udevice *testdev; + int ret, findret; + + /* + * For each test device found in fdt like: "a-test", "b-test", etc., + * use its name and try to get it by uclass_get_device_by_name(). + * On success check if: + * - returned finddev' is active + * - current 'testdev' name is equal to the returned 'finddev' name + * - current 'testdev' pointer is equal to the returned 'finddev' + * + * We asserts that the 'testdev' is active on each loop entry, so we + * could be sure that the 'finddev' is activated too, but for sure + * we check it again. + * + * We assume that, each uclass's device name is unique, so if not, then + * this will fail on checking condition: testdev == finddev, since the + * uclass_get_device_by_name(), returns the first device by given name. + */ + for (ret = uclass_first_device(UCLASS_TEST_FDT, &testdev); + testdev; + ret = uclass_next_device(&testdev)) { + ut_assertok(ret); + ut_assert(testdev); + ut_assert(device_active(testdev)); + + findret = uclass_get_device_by_name(UCLASS_TEST_FDT, + testdev->name, + &finddev); + + ut_assertok(findret); + ut_assert(finddev); + ut_assert(device_active(finddev)); + ut_asserteq_str(testdev->name, finddev->name); + ut_asserteq_ptr(testdev, finddev); + } + + return 0; +} +DM_TEST(dm_test_uclass_devices_get_by_name, UT_TESTF_SCAN_FDT); + +static int dm_test_device_get_uclass_id(struct unit_test_state *uts) +{ + struct udevice *dev; + + ut_assertok(uclass_get_device(UCLASS_TEST, 0, &dev)); + ut_asserteq(UCLASS_TEST, device_get_uclass_id(dev)); + + return 0; +} +DM_TEST(dm_test_device_get_uclass_id, UT_TESTF_SCAN_PDATA); + +static int dm_test_uclass_names(struct unit_test_state *uts) +{ + ut_asserteq_str("test", uclass_get_name(UCLASS_TEST)); + ut_asserteq(UCLASS_TEST, uclass_get_by_name("test")); + + return 0; +} +DM_TEST(dm_test_uclass_names, UT_TESTF_SCAN_PDATA); + +static int dm_test_inactive_child(struct unit_test_state *uts) +{ + struct udevice *parent, *dev1, *dev2; + + /* Skip the behaviour in test_post_probe() */ + uts->skip_post_probe = 1; + + ut_assertok(uclass_first_device_err(UCLASS_TEST, &parent)); + + /* + * Create a child but do not activate it. Calling the function again + * should return the same child. + */ + ut_asserteq(-ENODEV, device_find_first_inactive_child(parent, + UCLASS_TEST, &dev1)); + ut_assertok(device_bind(parent, DM_DRIVER_GET(test_drv), + "test_child", 0, ofnode_null(), &dev1)); + + ut_assertok(device_find_first_inactive_child(parent, UCLASS_TEST, + &dev2)); + ut_asserteq_ptr(dev1, dev2); + + ut_assertok(device_probe(dev1)); + ut_asserteq(-ENODEV, device_find_first_inactive_child(parent, + UCLASS_TEST, &dev2)); + + return 0; +} +DM_TEST(dm_test_inactive_child, UT_TESTF_SCAN_PDATA); + +/* Make sure all bound devices have a sequence number */ +static int dm_test_all_have_seq(struct unit_test_state *uts) +{ + struct udevice *dev; + struct uclass *uc; + + list_for_each_entry(uc, gd->uclass_root, sibling_node) { + list_for_each_entry(dev, &uc->dev_head, uclass_node) { + if (dev->seq_ == -1) + printf("Device '%s' has no seq (%d)\n", + dev->name, dev->seq_); + ut_assert(dev->seq_ != -1); + } + } + + return 0; +} +DM_TEST(dm_test_all_have_seq, UT_TESTF_SCAN_PDATA); + +static int dm_test_dma_offset(struct unit_test_state *uts) +{ + struct udevice *dev; + ofnode node; + + /* Make sure the bus's dma-ranges aren't taken into account here */ + node = ofnode_path("/mmio-bus@0"); + ut_assert(ofnode_valid(node)); + ut_assertok(uclass_get_device_by_ofnode(UCLASS_TEST_BUS, node, &dev)); + ut_asserteq_64(0, dev->dma_offset); + + /* Device behind a bus with dma-ranges */ + node = ofnode_path("/mmio-bus@0/subnode@0"); + ut_assert(ofnode_valid(node)); + ut_assertok(uclass_get_device_by_ofnode(UCLASS_TEST_FDT, node, &dev)); + ut_asserteq_64(-0x10000000ULL, dev->dma_offset); + + /* This one has no dma-ranges */ + node = ofnode_path("/mmio-bus@1"); + ut_assert(ofnode_valid(node)); + ut_assertok(uclass_get_device_by_ofnode(UCLASS_TEST_BUS, node, &dev)); + node = ofnode_path("/mmio-bus@1/subnode@0"); + ut_assert(ofnode_valid(node)); + ut_assertok(uclass_get_device_by_ofnode(UCLASS_TEST_FDT, node, &dev)); + ut_asserteq_64(0, dev->dma_offset); + + return 0; +} +DM_TEST(dm_test_dma_offset, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); diff --git a/roms/u-boot/test/dm/cpu.c b/roms/u-boot/test/dm/cpu.c new file mode 100644 index 000000000..ed12cafee --- /dev/null +++ b/roms/u-boot/test/dm/cpu.c @@ -0,0 +1,50 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * (C) Copyright 2018 + * Mario Six, Guntermann & Drunck GmbH, mario.six@gdsys.cc + */ + +#include <common.h> +#include <dm.h> +#include <log.h> +#include <dm/test.h> +#include <dm/uclass-internal.h> +#include <cpu.h> +#include <test/test.h> +#include <test/ut.h> + +static int dm_test_cpu(struct unit_test_state *uts) +{ + struct udevice *dev; + char text[128]; + struct cpu_info info; + + ut_assertok(cpu_probe_all()); + + /* Check that cpu_probe_all really activated all CPUs */ + for (uclass_find_first_device(UCLASS_CPU, &dev); + dev; + uclass_find_next_device(&dev)) + ut_assert(dev_get_flags(dev) & DM_FLAG_ACTIVATED); + + ut_assertok(uclass_get_device_by_name(UCLASS_CPU, "cpu-test1", &dev)); + ut_asserteq_ptr(cpu_get_current_dev(), dev); + ut_asserteq(cpu_is_current(dev), 1); + + ut_assertok(cpu_get_desc(dev, text, sizeof(text))); + ut_assertok(strcmp(text, "LEG Inc. SuperMegaUltraTurbo CPU No. 1")); + + ut_assertok(cpu_get_info(dev, &info)); + ut_asserteq(info.cpu_freq, 42 * 42 * 42 * 42 * 42); + ut_asserteq(info.features, 0x42424242); + ut_asserteq(info.address_width, 32); + + ut_asserteq(cpu_get_count(dev), 42); + + ut_assertok(cpu_get_vendor(dev, text, sizeof(text))); + ut_assertok(strcmp(text, "Languid Example Garbage Inc.")); + + return 0; +} + +DM_TEST(dm_test_cpu, UT_TESTF_SCAN_FDT); diff --git a/roms/u-boot/test/dm/cros_ec.c b/roms/u-boot/test/dm/cros_ec.c new file mode 100644 index 000000000..30cb70e08 --- /dev/null +++ b/roms/u-boot/test/dm/cros_ec.c @@ -0,0 +1,178 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright 2021 Google LLC + */ + +#include <common.h> +#include <cros_ec.h> +#include <dm.h> +#include <asm/test.h> +#include <dm/test.h> +#include <test/ut.h> + +static int dm_test_cros_ec_hello(struct unit_test_state *uts) +{ + struct udevice *dev; + uint val; + + ut_assertok(uclass_first_device_err(UCLASS_CROS_EC, &dev)); + + ut_assertok(cros_ec_hello(dev, NULL)); + + val = 0xdead1357; + ut_assertok(cros_ec_hello(dev, &val)); + ut_asserteq(0xdead1357, val); + + sandbox_cros_ec_set_test_flags(dev, CROSECT_BREAK_HELLO); + ut_asserteq(-ENOTSYNC, cros_ec_hello(dev, &val)); + ut_asserteq(0x12345678, val); + + return 0; +} +DM_TEST(dm_test_cros_ec_hello, UT_TESTF_SCAN_FDT); + +static int dm_test_cros_ec_sku_id(struct unit_test_state *uts) +{ + struct udevice *dev; + + ut_assertok(uclass_first_device_err(UCLASS_CROS_EC, &dev)); + ut_asserteq(1234, cros_ec_get_sku_id(dev)); + + /* try the command */ + console_record_reset(); + ut_assertok(run_command("crosec sku", 0)); + ut_assert_nextline("1234"); + ut_assert_console_end(); + + return 0; +} +DM_TEST(dm_test_cros_ec_sku_id, UT_TESTF_SCAN_FDT); + +static int dm_test_cros_ec_features(struct unit_test_state *uts) +{ + struct udevice *dev; + u64 feat; + + ut_assertok(uclass_first_device_err(UCLASS_CROS_EC, &dev)); + ut_assertok(cros_ec_get_features(dev, &feat)); + ut_asserteq_64(1U << EC_FEATURE_FLASH | 1U << EC_FEATURE_I2C | + 1u << EC_FEATURE_VSTORE | + 1ULL << EC_FEATURE_UNIFIED_WAKE_MASKS | 1ULL << EC_FEATURE_ISH, + feat); + + ut_asserteq(true, cros_ec_check_feature(dev, EC_FEATURE_I2C)); + ut_asserteq(false, cros_ec_check_feature(dev, EC_FEATURE_MOTION_SENSE)); + ut_asserteq(true, cros_ec_check_feature(dev, EC_FEATURE_ISH)); + + /* try the command */ + console_record_reset(); + ut_assertok(run_command("crosec features", 0)); + ut_assert_nextline("flash"); + ut_assert_nextline("i2c"); + ut_assert_nextline("vstore"); + ut_assert_nextline("unified_wake_masks"); + ut_assert_nextline("ish"); + ut_assert_console_end(); + + return 0; +} +DM_TEST(dm_test_cros_ec_features, UT_TESTF_SCAN_FDT); + +static int dm_test_cros_ec_switches(struct unit_test_state *uts) +{ + struct udevice *dev; + + ut_assertok(uclass_first_device_err(UCLASS_CROS_EC, &dev)); + ut_asserteq(0, cros_ec_get_switches(dev)); + + /* try the command */ + console_record_reset(); + ut_assertok(run_command("crosec switches", 0)); + ut_assert_console_end(); + + /* Open the lid and check the switch changes */ + sandbox_cros_ec_set_test_flags(dev, CROSECT_LID_OPEN); + ut_asserteq(EC_SWITCH_LID_OPEN, cros_ec_get_switches(dev)); + + /* try the command */ + console_record_reset(); + ut_assertok(run_command("crosec switches", 0)); + ut_assert_nextline("lid open"); + ut_assert_console_end(); + + return 0; +} +DM_TEST(dm_test_cros_ec_switches, UT_TESTF_SCAN_FDT); + +static int dm_test_cros_ec_events(struct unit_test_state *uts) +{ + struct udevice *dev; + u32 events; + + ut_assertok(uclass_first_device_err(UCLASS_CROS_EC, &dev)); + ut_assertok(cros_ec_get_host_events(dev, &events)); + ut_asserteq(0, events); + + /* try the command */ + console_record_reset(); + ut_assertok(run_command("crosec events", 0)); + ut_assert_nextline("00000000"); + ut_assert_console_end(); + + /* Open the lid and check the event appears */ + sandbox_cros_ec_set_test_flags(dev, CROSECT_LID_OPEN); + ut_assertok(cros_ec_get_host_events(dev, &events)); + ut_asserteq(EC_HOST_EVENT_MASK(EC_HOST_EVENT_LID_OPEN), events); + + /* try the command */ + console_record_reset(); + ut_assertok(run_command("crosec events", 0)); + ut_assert_nextline("00000002"); + ut_assert_nextline("lid_open"); + ut_assert_console_end(); + + /* Clear the event */ + ut_assertok(cros_ec_clear_host_events(dev, + EC_HOST_EVENT_MASK(EC_HOST_EVENT_LID_OPEN))); + ut_assertok(cros_ec_get_host_events(dev, &events)); + ut_asserteq(0, events); + + return 0; +} +DM_TEST(dm_test_cros_ec_events, UT_TESTF_SCAN_FDT); + +static int dm_test_cros_ec_vstore(struct unit_test_state *uts) +{ + const int size = EC_VSTORE_SLOT_SIZE; + u8 test_data[size], data[size]; + struct udevice *dev; + u32 locked; + int i; + + ut_assertok(uclass_first_device_err(UCLASS_CROS_EC, &dev)); + ut_asserteq(true, cros_ec_vstore_supported(dev)); + + ut_asserteq(4, cros_ec_vstore_info(dev, &locked)); + ut_asserteq(0, locked); + + /* Write some data */ + for (i = 0; i < size; i++) + test_data[i] = ' ' + i; + ut_assertok(cros_ec_vstore_write(dev, 2, test_data, size)); + + /* Check it is locked */ + ut_asserteq(4, cros_ec_vstore_info(dev, &locked)); + ut_asserteq(1 << 2, locked); + + /* Read it back and compare */ + ut_assertok(cros_ec_vstore_read(dev, 2, data)); + ut_asserteq_mem(test_data, data, size); + + /* Try another slot to make sure it is empty */ + ut_assertok(cros_ec_vstore_read(dev, 0, data)); + for (i = 0; i < size; i++) + ut_asserteq(0, data[i]); + + return 0; +} +DM_TEST(dm_test_cros_ec_vstore, UT_TESTF_SCAN_FDT); diff --git a/roms/u-boot/test/dm/devres.c b/roms/u-boot/test/dm/devres.c new file mode 100644 index 000000000..4f959d11d --- /dev/null +++ b/roms/u-boot/test/dm/devres.c @@ -0,0 +1,189 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Tests for the devres ( + * + * Copyright 2019 Google LLC + */ + +#include <common.h> +#include <errno.h> +#include <dm.h> +#include <log.h> +#include <malloc.h> +#include <dm/device-internal.h> +#include <dm/devres.h> +#include <dm/test.h> +#include <dm/uclass-internal.h> +#include <test/ut.h> + +/* Test that devm_kmalloc() allocates memory, free when device is removed */ +static int dm_test_devres_alloc(struct unit_test_state *uts) +{ + ulong mem_start, mem_dev, mem_kmalloc; + struct udevice *dev; + void *ptr; + + mem_start = ut_check_delta(0); + ut_assertok(uclass_first_device_err(UCLASS_TEST, &dev)); + mem_dev = ut_check_delta(mem_start); + ut_assert(mem_dev > 0); + + /* This should increase allocated memory */ + ptr = devm_kmalloc(dev, TEST_DEVRES_SIZE, 0); + ut_assert(ptr != NULL); + mem_kmalloc = ut_check_delta(mem_dev); + ut_assert(mem_kmalloc > 0); + + /* Check that ptr is freed */ + device_remove(dev, DM_REMOVE_NORMAL); + ut_asserteq(0, ut_check_delta(mem_start)); + + return 0; +} +DM_TEST(dm_test_devres_alloc, UT_TESTF_SCAN_PDATA); + +/* Test devm_kfree() can be used to free memory too */ +static int dm_test_devres_free(struct unit_test_state *uts) +{ + ulong mem_start, mem_dev, mem_kmalloc; + struct udevice *dev; + void *ptr; + + mem_start = ut_check_delta(0); + ut_assertok(uclass_first_device_err(UCLASS_TEST, &dev)); + mem_dev = ut_check_delta(mem_start); + ut_assert(mem_dev > 0); + + ptr = devm_kmalloc(dev, TEST_DEVRES_SIZE, 0); + ut_assert(ptr != NULL); + mem_kmalloc = ut_check_delta(mem_dev); + ut_assert(mem_kmalloc > 0); + + /* Free the ptr and check that memory usage goes down */ + devm_kfree(dev, ptr); + ut_assert(ut_check_delta(mem_kmalloc) < 0); + + device_remove(dev, DM_REMOVE_NORMAL); + ut_asserteq(0, ut_check_delta(mem_start)); + + return 0; +} +DM_TEST(dm_test_devres_free, UT_TESTF_SCAN_PDATA); + + +/* Test that kzalloc() returns memory that is zeroed */ +static int dm_test_devres_kzalloc(struct unit_test_state *uts) +{ + struct udevice *dev; + u8 *ptr, val; + int i; + + ut_assertok(uclass_first_device_err(UCLASS_TEST, &dev)); + + ptr = devm_kzalloc(dev, TEST_DEVRES_SIZE, 0); + ut_assert(ptr != NULL); + for (val = 0, i = 0; i < TEST_DEVRES_SIZE; i++) + val |= *ptr; + ut_asserteq(0, val); + + return 0; +} +DM_TEST(dm_test_devres_kzalloc, UT_TESTF_SCAN_PDATA); + +/* Test that devm_kmalloc_array() allocates an array that can be set */ +static int dm_test_devres_kmalloc_array(struct unit_test_state *uts) +{ + ulong mem_start, mem_dev; + struct udevice *dev; + u8 *ptr; + + mem_start = ut_check_delta(0); + ut_assertok(uclass_first_device_err(UCLASS_TEST, &dev)); + mem_dev = ut_check_delta(mem_start); + + ptr = devm_kmalloc_array(dev, TEST_DEVRES_COUNT, TEST_DEVRES_SIZE, 0); + ut_assert(ptr != NULL); + memset(ptr, '\xff', TEST_DEVRES_TOTAL); + ut_assert(ut_check_delta(mem_dev) > 0); + + device_remove(dev, DM_REMOVE_NORMAL); + ut_asserteq(0, ut_check_delta(mem_start)); + + return 0; +} +DM_TEST(dm_test_devres_kmalloc_array, UT_TESTF_SCAN_PDATA); + +/* Test that devm_kcalloc() allocates a zeroed array */ +static int dm_test_devres_kcalloc(struct unit_test_state *uts) +{ + ulong mem_start, mem_dev; + struct udevice *dev; + u8 *ptr, val; + int i; + + mem_start = ut_check_delta(0); + ut_assertok(uclass_first_device_err(UCLASS_TEST, &dev)); + mem_dev = ut_check_delta(mem_start); + ut_assert(mem_dev > 0); + + /* This should increase allocated memory */ + ptr = devm_kcalloc(dev, TEST_DEVRES_SIZE, TEST_DEVRES_COUNT, 0); + ut_assert(ptr != NULL); + ut_assert(ut_check_delta(mem_dev) > 0); + for (val = 0, i = 0; i < TEST_DEVRES_TOTAL; i++) + val |= *ptr; + ut_asserteq(0, val); + + /* Check that ptr is freed */ + device_remove(dev, DM_REMOVE_NORMAL); + ut_asserteq(0, ut_check_delta(mem_start)); + + return 0; +} +DM_TEST(dm_test_devres_kcalloc, UT_TESTF_SCAN_PDATA); + +/* Test devres releases resources automatically as expected */ +static int dm_test_devres_phase(struct unit_test_state *uts) +{ + struct devres_stats stats; + struct udevice *dev; + + /* + * The device is bound already, so find it and check that it has the + * allocation created in the bind() method. + */ + ut_assertok(uclass_find_first_device(UCLASS_TEST_DEVRES, &dev)); + ut_assertnonnull(dev); + devres_get_stats(dev, &stats); + ut_asserteq(1, stats.allocs); + ut_asserteq(TEST_DEVRES_SIZE, stats.total_size); + + /* Getting plat should add one allocation */ + ut_assertok(device_of_to_plat(dev)); + devres_get_stats(dev, &stats); + ut_asserteq(2, stats.allocs); + ut_asserteq(TEST_DEVRES_SIZE + TEST_DEVRES_SIZE3, stats.total_size); + + /* Probing the device should add one allocation */ + ut_assertok(uclass_first_device(UCLASS_TEST_DEVRES, &dev)); + ut_assert(dev != NULL); + devres_get_stats(dev, &stats); + ut_asserteq(3, stats.allocs); + ut_asserteq(TEST_DEVRES_SIZE + TEST_DEVRES_SIZE2 + TEST_DEVRES_SIZE3, + stats.total_size); + + /* Removing the device should drop both those allocations */ + device_remove(dev, DM_REMOVE_NORMAL); + devres_get_stats(dev, &stats); + ut_asserteq(1, stats.allocs); + ut_asserteq(TEST_DEVRES_SIZE, stats.total_size); + + /* Unbinding removes the other. Note this access a freed pointer */ + device_unbind(dev); + devres_get_stats(dev, &stats); + ut_asserteq(0, stats.allocs); + ut_asserteq(0, stats.total_size); + + return 0; +} +DM_TEST(dm_test_devres_phase, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); diff --git a/roms/u-boot/test/dm/dma.c b/roms/u-boot/test/dm/dma.c new file mode 100644 index 000000000..cce47cb21 --- /dev/null +++ b/roms/u-boot/test/dm/dma.c @@ -0,0 +1,125 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Direct Memory Access U-Class tests + * + * Copyright (C) 2018 Texas Instruments Incorporated <www.ti.com> + * Grygorii Strashko <grygorii.strashko@ti.com> + */ + +#include <common.h> +#include <dm.h> +#include <malloc.h> +#include <dm/test.h> +#include <dma.h> +#include <test/test.h> +#include <test/ut.h> + +static int dm_test_dma_m2m(struct unit_test_state *uts) +{ + struct udevice *dev; + struct dma dma_m2m; + u8 src_buf[512]; + u8 dst_buf[512]; + size_t len = 512; + int i; + + ut_assertok(uclass_get_device_by_name(UCLASS_DMA, "dma", &dev)); + ut_assertok(dma_get_by_name(dev, "m2m", &dma_m2m)); + + memset(dst_buf, 0, len); + for (i = 0; i < len; i++) + src_buf[i] = i; + + ut_assertok(dma_memcpy(dst_buf, src_buf, len)); + ut_asserteq_mem(src_buf, dst_buf, len); + + return 0; +} +DM_TEST(dm_test_dma_m2m, UT_TESTF_SCAN_FDT); + +static int dm_test_dma(struct unit_test_state *uts) +{ + struct udevice *dev; + struct dma dma_tx, dma_rx; + u8 src_buf[512]; + u8 dst_buf[512]; + void *dst_ptr; + size_t len = 512; + u32 meta1, meta2; + int i; + + ut_assertok(uclass_get_device_by_name(UCLASS_DMA, "dma", &dev)); + + ut_assertok(dma_get_by_name(dev, "tx0", &dma_tx)); + ut_assertok(dma_get_by_name(dev, "rx0", &dma_rx)); + + ut_assertok(dma_enable(&dma_tx)); + ut_assertok(dma_enable(&dma_rx)); + + memset(dst_buf, 0, len); + for (i = 0; i < len; i++) + src_buf[i] = i; + meta1 = 0xADADDEAD; + meta2 = 0; + dst_ptr = &dst_buf; + + ut_assertok(dma_send(&dma_tx, src_buf, len, &meta1)); + + ut_asserteq(len, dma_receive(&dma_rx, &dst_ptr, &meta2)); + ut_asserteq(0xADADDEAD, meta2); + + ut_assertok(dma_disable(&dma_tx)); + ut_assertok(dma_disable(&dma_rx)); + + ut_assertok(dma_free(&dma_tx)); + ut_assertok(dma_free(&dma_rx)); + ut_asserteq_mem(src_buf, dst_buf, len); + + return 0; +} +DM_TEST(dm_test_dma, UT_TESTF_SCAN_FDT); + +static int dm_test_dma_rx(struct unit_test_state *uts) +{ + struct udevice *dev; + struct dma dma_tx, dma_rx; + u8 src_buf[512]; + u8 dst_buf[512]; + void *dst_ptr; + size_t len = 512; + u32 meta1, meta2; + int i; + + ut_assertok(uclass_get_device_by_name(UCLASS_DMA, "dma", &dev)); + + ut_assertok(dma_get_by_name(dev, "tx0", &dma_tx)); + ut_assertok(dma_get_by_name(dev, "rx0", &dma_rx)); + + ut_assertok(dma_enable(&dma_tx)); + ut_assertok(dma_enable(&dma_rx)); + + memset(dst_buf, 0, len); + for (i = 0; i < len; i++) + src_buf[i] = i; + meta1 = 0xADADDEAD; + meta2 = 0; + dst_ptr = NULL; + + ut_assertok(dma_prepare_rcv_buf(&dma_tx, dst_buf, len)); + + ut_assertok(dma_send(&dma_tx, src_buf, len, &meta1)); + + ut_asserteq(len, dma_receive(&dma_rx, &dst_ptr, &meta2)); + ut_asserteq(0xADADDEAD, meta2); + ut_asserteq_ptr(dst_buf, dst_ptr); + + ut_assertok(dma_disable(&dma_tx)); + ut_assertok(dma_disable(&dma_rx)); + + ut_assertok(dma_free(&dma_tx)); + ut_assertok(dma_free(&dma_rx)); + ut_asserteq_mem(src_buf, dst_buf, len); + + return 0; +} +DM_TEST(dm_test_dma_rx, UT_TESTF_SCAN_FDT); diff --git a/roms/u-boot/test/dm/dsa.c b/roms/u-boot/test/dm/dsa.c new file mode 100644 index 000000000..18c177646 --- /dev/null +++ b/roms/u-boot/test/dm/dsa.c @@ -0,0 +1,82 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright 2020-2021 NXP Semiconductors + */ + +#include <net/dsa.h> +#include <dm/test.h> +#include <test/ut.h> +#include <net.h> +#include <dm/uclass-internal.h> +#include <dm/device-internal.h> + +/* This test exercises the major dsa.h API functions, after making sure + * that the DSA ports and the master Eth are correctly probed. + */ +static int dm_test_dsa_probe(struct unit_test_state *uts) +{ + struct udevice *dev_dsa, *dev_port, *dev_master; + struct dsa_pdata *dsa_pdata; + enum uclass_id id; + + id = uclass_get_by_name("dsa"); + ut_assert(id == UCLASS_DSA); + + ut_assertok(uclass_find_device_by_name(UCLASS_DSA, "dsa-test", + &dev_dsa)); + ut_assertok(uclass_find_device_by_name(UCLASS_ETH, "dsa-test-eth", + &dev_master)); + ut_assertok(device_probe(dev_master)); + + ut_assertok(uclass_find_device_by_name(UCLASS_ETH, "dsa-test@0", + &dev_port)); + ut_assertok(device_probe(dev_port)); + + ut_assertok(uclass_find_device_by_name(UCLASS_ETH, "dsa-test@1", + &dev_port)); + ut_assertok(device_probe(dev_port)); + + /* exercise DSA API */ + dsa_pdata = dev_get_uclass_plat(dev_dsa); + ut_assertnonnull(dsa_pdata); + /* includes CPU port */ + ut_assert(dsa_pdata->num_ports == 3); + + ut_assertok(uclass_find_device_by_name(UCLASS_ETH, "lan0", + &dev_port)); + ut_assertok(device_probe(dev_port)); + + ut_assertok(uclass_find_device_by_name(UCLASS_ETH, "lan1", + &dev_port)); + ut_assertok(device_probe(dev_port)); + + dev_master = dsa_get_master(dev_dsa); + ut_assertnonnull(dev_master); + ut_asserteq_str("dsa-test-eth", dev_master->name); + + return 0; +} + +DM_TEST(dm_test_dsa_probe, UT_TESTF_SCAN_FDT); + +/* This test sends ping requests with the local address through each DSA port + * via the sandbox DSA master Eth. + */ +static int dm_test_dsa(struct unit_test_state *uts) +{ + net_ping_ip = string_to_ip("1.2.3.5"); + + env_set("ethact", "eth2"); + ut_assertok(net_loop(PING)); + + env_set("ethact", "lan0"); + ut_assertok(net_loop(PING)); + env_set("ethact", "lan1"); + ut_assertok(net_loop(PING)); + + env_set("ethact", ""); + + return 0; +} + +DM_TEST(dm_test_dsa, UT_TESTF_SCAN_FDT); diff --git a/roms/u-boot/test/dm/dsi_host.c b/roms/u-boot/test/dm/dsi_host.c new file mode 100644 index 000000000..6e0a5df70 --- /dev/null +++ b/roms/u-boot/test/dm/dsi_host.c @@ -0,0 +1,59 @@ +// SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause +/* + * Copyright (C) 2019 STMicroelectronics - All Rights Reserved + * Author(s): Yannick Fertre <yannick.fertre@st.com> for STMicroelectronics. + */ + +#include <common.h> +#include <dm.h> +#include <dsi_host.h> +#include <asm/state.h> +#include <asm/test.h> +#include <dm/test.h> +#include <test/test.h> +#include <test/ut.h> + +static int dm_test_dsi_host_phy_init(void *priv_data) +{ + return 0; +} + +static void dm_test_dsi_host_phy_post_set_mode(void *priv_data, + unsigned long mode_flags) +{ +} + +static int dm_test_dsi_host_phy_get_lane_mbps(void *priv_data, + struct display_timing *timings, + u32 lanes, + u32 format, + unsigned int *lane_mbps) +{ + return 0; +} + +static const struct mipi_dsi_phy_ops dm_test_dsi_host_phy_ops = { + .init = dm_test_dsi_host_phy_init, + .get_lane_mbps = dm_test_dsi_host_phy_get_lane_mbps, + .post_set_mode = dm_test_dsi_host_phy_post_set_mode, +}; + +/* Test that dsi_host driver functions are called */ +static int dm_test_dsi_host(struct unit_test_state *uts) +{ + struct udevice *dev; + struct mipi_dsi_device device; + struct display_timing timings; + unsigned int max_data_lanes = 4; + + ut_assertok(uclass_first_device_err(UCLASS_DSI_HOST, &dev)); + + ut_assertok(dsi_host_init(dev, &device, &timings, max_data_lanes, + &dm_test_dsi_host_phy_ops)); + + ut_assertok(dsi_host_enable(dev)); + + return 0; +} + +DM_TEST(dm_test_dsi_host, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); diff --git a/roms/u-boot/test/dm/eth.c b/roms/u-boot/test/dm/eth.c new file mode 100644 index 000000000..e4ee69561 --- /dev/null +++ b/roms/u-boot/test/dm/eth.c @@ -0,0 +1,433 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2015 National Instruments + * + * (C) Copyright 2015 + * Joe Hershberger <joe.hershberger@ni.com> + */ + +#include <common.h> +#include <dm.h> +#include <env.h> +#include <fdtdec.h> +#include <log.h> +#include <malloc.h> +#include <net.h> +#include <asm/eth.h> +#include <dm/test.h> +#include <dm/device-internal.h> +#include <dm/uclass-internal.h> +#include <test/test.h> +#include <test/ut.h> + +#define DM_TEST_ETH_NUM 4 + +static int dm_test_eth(struct unit_test_state *uts) +{ + net_ping_ip = string_to_ip("1.1.2.2"); + + env_set("ethact", "eth@10002000"); + ut_assertok(net_loop(PING)); + ut_asserteq_str("eth@10002000", env_get("ethact")); + + env_set("ethact", "eth@10003000"); + ut_assertok(net_loop(PING)); + ut_asserteq_str("eth@10003000", env_get("ethact")); + + env_set("ethact", "eth@10004000"); + ut_assertok(net_loop(PING)); + ut_asserteq_str("eth@10004000", env_get("ethact")); + + return 0; +} +DM_TEST(dm_test_eth, UT_TESTF_SCAN_FDT); + +static int dm_test_eth_alias(struct unit_test_state *uts) +{ + net_ping_ip = string_to_ip("1.1.2.2"); + env_set("ethact", "eth0"); + ut_assertok(net_loop(PING)); + ut_asserteq_str("eth@10002000", env_get("ethact")); + + env_set("ethact", "eth6"); + ut_assertok(net_loop(PING)); + ut_asserteq_str("eth@10004000", env_get("ethact")); + + /* Expected to fail since eth1 is not defined in the device tree */ + env_set("ethact", "eth1"); + ut_assertok(net_loop(PING)); + ut_asserteq_str("eth@10002000", env_get("ethact")); + + env_set("ethact", "eth5"); + ut_assertok(net_loop(PING)); + ut_asserteq_str("eth@10003000", env_get("ethact")); + + return 0; +} +DM_TEST(dm_test_eth_alias, UT_TESTF_SCAN_FDT); + +static int dm_test_eth_prime(struct unit_test_state *uts) +{ + net_ping_ip = string_to_ip("1.1.2.2"); + + /* Expected to be "eth@10003000" because of ethprime variable */ + env_set("ethact", NULL); + env_set("ethprime", "eth5"); + ut_assertok(net_loop(PING)); + ut_asserteq_str("eth@10003000", env_get("ethact")); + + /* Expected to be "eth@10002000" because it is first */ + env_set("ethact", NULL); + env_set("ethprime", NULL); + ut_assertok(net_loop(PING)); + ut_asserteq_str("eth@10002000", env_get("ethact")); + + return 0; +} +DM_TEST(dm_test_eth_prime, UT_TESTF_SCAN_FDT); + +/** + * This test case is trying to test the following scenario: + * - All ethernet devices are not probed + * - "ethaddr" for all ethernet devices are not set + * - "ethact" is set to a valid ethernet device name + * + * With Sandbox default test configuration, all ethernet devices are + * probed after power-up, so we have to manually create such scenario: + * - Remove all ethernet devices + * - Remove all "ethaddr" environment variables + * - Set "ethact" to the first ethernet device + * + * Do a ping test to see if anything goes wrong. + */ +static int dm_test_eth_act(struct unit_test_state *uts) +{ + struct udevice *dev[DM_TEST_ETH_NUM]; + const char *ethname[DM_TEST_ETH_NUM] = {"eth@10002000", "eth@10003000", + "sbe5", "eth@10004000"}; + const char *addrname[DM_TEST_ETH_NUM] = {"ethaddr", "eth5addr", + "eth3addr", "eth6addr"}; + char ethaddr[DM_TEST_ETH_NUM][18]; + int i; + + memset(ethaddr, '\0', sizeof(ethaddr)); + net_ping_ip = string_to_ip("1.1.2.2"); + + /* Prepare the test scenario */ + for (i = 0; i < DM_TEST_ETH_NUM; i++) { + ut_assertok(uclass_find_device_by_name(UCLASS_ETH, + ethname[i], &dev[i])); + ut_assertok(device_remove(dev[i], DM_REMOVE_NORMAL)); + + /* Invalidate MAC address */ + strncpy(ethaddr[i], env_get(addrname[i]), 17); + /* Must disable access protection for ethaddr before clearing */ + env_set(".flags", addrname[i]); + env_set(addrname[i], NULL); + } + + /* Set ethact to "eth@10002000" */ + env_set("ethact", ethname[0]); + + /* Segment fault might happen if something is wrong */ + ut_asserteq(-ENODEV, net_loop(PING)); + + for (i = 0; i < DM_TEST_ETH_NUM; i++) { + /* Restore the env */ + env_set(".flags", addrname[i]); + env_set(addrname[i], ethaddr[i]); + + /* Probe the device again */ + ut_assertok(device_probe(dev[i])); + } + env_set(".flags", NULL); + env_set("ethact", NULL); + + return 0; +} +DM_TEST(dm_test_eth_act, UT_TESTF_SCAN_FDT); + +/* The asserts include a return on fail; cleanup in the caller */ +static int _dm_test_eth_rotate1(struct unit_test_state *uts) +{ + /* Make sure that the default is to rotate to the next interface */ + env_set("ethact", "eth@10004000"); + ut_assertok(net_loop(PING)); + ut_asserteq_str("eth@10002000", env_get("ethact")); + + /* If ethrotate is no, then we should fail on a bad MAC */ + env_set("ethact", "eth@10004000"); + env_set("ethrotate", "no"); + ut_asserteq(-EINVAL, net_loop(PING)); + ut_asserteq_str("eth@10004000", env_get("ethact")); + + return 0; +} + +static int _dm_test_eth_rotate2(struct unit_test_state *uts) +{ + /* Make sure we can skip invalid devices */ + env_set("ethact", "eth@10004000"); + ut_assertok(net_loop(PING)); + ut_asserteq_str("eth@10004000", env_get("ethact")); + + /* Make sure we can handle device name which is not eth# */ + env_set("ethact", "sbe5"); + ut_assertok(net_loop(PING)); + ut_asserteq_str("sbe5", env_get("ethact")); + + return 0; +} + +static int dm_test_eth_rotate(struct unit_test_state *uts) +{ + char ethaddr[18]; + int retval; + + /* Set target IP to mock ping */ + net_ping_ip = string_to_ip("1.1.2.2"); + + /* Invalidate eth1's MAC address */ + memset(ethaddr, '\0', sizeof(ethaddr)); + strncpy(ethaddr, env_get("eth6addr"), 17); + /* Must disable access protection for eth6addr before clearing */ + env_set(".flags", "eth6addr"); + env_set("eth6addr", NULL); + + retval = _dm_test_eth_rotate1(uts); + + /* Restore the env */ + env_set("eth6addr", ethaddr); + env_set("ethrotate", NULL); + + if (!retval) { + /* Invalidate eth0's MAC address */ + strncpy(ethaddr, env_get("ethaddr"), 17); + /* Must disable access protection for ethaddr before clearing */ + env_set(".flags", "ethaddr"); + env_set("ethaddr", NULL); + + retval = _dm_test_eth_rotate2(uts); + + /* Restore the env */ + env_set("ethaddr", ethaddr); + } + /* Restore the env */ + env_set(".flags", NULL); + + return retval; +} +DM_TEST(dm_test_eth_rotate, UT_TESTF_SCAN_FDT); + +/* The asserts include a return on fail; cleanup in the caller */ +static int _dm_test_net_retry(struct unit_test_state *uts) +{ + /* + * eth1 is disabled and netretry is yes, so the ping should succeed and + * the active device should be eth0 + */ + sandbox_eth_disable_response(1, true); + env_set("ethact", "lan1"); + env_set("netretry", "yes"); + sandbox_eth_skip_timeout(); + ut_assertok(net_loop(PING)); + ut_asserteq_str("eth@10002000", env_get("ethact")); + + /* + * eth1 is disabled and netretry is no, so the ping should fail and the + * active device should be eth1 + */ + env_set("ethact", "lan1"); + env_set("netretry", "no"); + sandbox_eth_skip_timeout(); + ut_asserteq(-ENONET, net_loop(PING)); + ut_asserteq_str("lan1", env_get("ethact")); + + return 0; +} + +static int dm_test_net_retry(struct unit_test_state *uts) +{ + int retval; + + net_ping_ip = string_to_ip("1.1.2.2"); + + retval = _dm_test_net_retry(uts); + + /* Restore the env */ + env_set("netretry", NULL); + sandbox_eth_disable_response(1, false); + + return retval; +} +DM_TEST(dm_test_net_retry, UT_TESTF_SCAN_FDT); + +static int sb_check_arp_reply(struct udevice *dev, void *packet, + unsigned int len) +{ + struct eth_sandbox_priv *priv = dev_get_priv(dev); + struct ethernet_hdr *eth = packet; + struct arp_hdr *arp; + /* Used by all of the ut_assert macros */ + struct unit_test_state *uts = priv->priv; + + if (ntohs(eth->et_protlen) != PROT_ARP) + return 0; + + arp = packet + ETHER_HDR_SIZE; + + if (ntohs(arp->ar_op) != ARPOP_REPLY) + return 0; + + /* This test would be worthless if we are not waiting */ + ut_assert(arp_is_waiting()); + + /* Validate response */ + ut_asserteq_mem(eth->et_src, net_ethaddr, ARP_HLEN); + ut_asserteq_mem(eth->et_dest, priv->fake_host_hwaddr, ARP_HLEN); + ut_assert(eth->et_protlen == htons(PROT_ARP)); + + ut_assert(arp->ar_hrd == htons(ARP_ETHER)); + ut_assert(arp->ar_pro == htons(PROT_IP)); + ut_assert(arp->ar_hln == ARP_HLEN); + ut_assert(arp->ar_pln == ARP_PLEN); + ut_asserteq_mem(&arp->ar_sha, net_ethaddr, ARP_HLEN); + ut_assert(net_read_ip(&arp->ar_spa).s_addr == net_ip.s_addr); + ut_asserteq_mem(&arp->ar_tha, priv->fake_host_hwaddr, ARP_HLEN); + ut_assert(net_read_ip(&arp->ar_tpa).s_addr == + string_to_ip("1.1.2.4").s_addr); + + return 0; +} + +static int sb_with_async_arp_handler(struct udevice *dev, void *packet, + unsigned int len) +{ + struct eth_sandbox_priv *priv = dev_get_priv(dev); + struct ethernet_hdr *eth = packet; + struct arp_hdr *arp = packet + ETHER_HDR_SIZE; + int ret; + + /* + * If we are about to generate a reply to ARP, first inject a request + * from another host + */ + if (ntohs(eth->et_protlen) == PROT_ARP && + ntohs(arp->ar_op) == ARPOP_REQUEST) { + /* Make sure sandbox_eth_recv_arp_req() knows who is asking */ + priv->fake_host_ipaddr = string_to_ip("1.1.2.4"); + + ret = sandbox_eth_recv_arp_req(dev); + if (ret) + return ret; + } + + sandbox_eth_arp_req_to_reply(dev, packet, len); + sandbox_eth_ping_req_to_reply(dev, packet, len); + + return sb_check_arp_reply(dev, packet, len); +} + +static int dm_test_eth_async_arp_reply(struct unit_test_state *uts) +{ + net_ping_ip = string_to_ip("1.1.2.2"); + + sandbox_eth_set_tx_handler(0, sb_with_async_arp_handler); + /* Used by all of the ut_assert macros in the tx_handler */ + sandbox_eth_set_priv(0, uts); + + env_set("ethact", "eth@10002000"); + ut_assertok(net_loop(PING)); + ut_asserteq_str("eth@10002000", env_get("ethact")); + + sandbox_eth_set_tx_handler(0, NULL); + + return 0; +} + +DM_TEST(dm_test_eth_async_arp_reply, UT_TESTF_SCAN_FDT); + +static int sb_check_ping_reply(struct udevice *dev, void *packet, + unsigned int len) +{ + struct eth_sandbox_priv *priv = dev_get_priv(dev); + struct ethernet_hdr *eth = packet; + struct ip_udp_hdr *ip; + struct icmp_hdr *icmp; + /* Used by all of the ut_assert macros */ + struct unit_test_state *uts = priv->priv; + + if (ntohs(eth->et_protlen) != PROT_IP) + return 0; + + ip = packet + ETHER_HDR_SIZE; + + if (ip->ip_p != IPPROTO_ICMP) + return 0; + + icmp = (struct icmp_hdr *)&ip->udp_src; + + if (icmp->type != ICMP_ECHO_REPLY) + return 0; + + /* This test would be worthless if we are not waiting */ + ut_assert(arp_is_waiting()); + + /* Validate response */ + ut_asserteq_mem(eth->et_src, net_ethaddr, ARP_HLEN); + ut_asserteq_mem(eth->et_dest, priv->fake_host_hwaddr, ARP_HLEN); + ut_assert(eth->et_protlen == htons(PROT_IP)); + + ut_assert(net_read_ip(&ip->ip_src).s_addr == net_ip.s_addr); + ut_assert(net_read_ip(&ip->ip_dst).s_addr == + string_to_ip("1.1.2.4").s_addr); + + return 0; +} + +static int sb_with_async_ping_handler(struct udevice *dev, void *packet, + unsigned int len) +{ + struct eth_sandbox_priv *priv = dev_get_priv(dev); + struct ethernet_hdr *eth = packet; + struct arp_hdr *arp = packet + ETHER_HDR_SIZE; + int ret; + + /* + * If we are about to generate a reply to ARP, first inject a request + * from another host + */ + if (ntohs(eth->et_protlen) == PROT_ARP && + ntohs(arp->ar_op) == ARPOP_REQUEST) { + /* Make sure sandbox_eth_recv_arp_req() knows who is asking */ + priv->fake_host_ipaddr = string_to_ip("1.1.2.4"); + + ret = sandbox_eth_recv_ping_req(dev); + if (ret) + return ret; + } + + sandbox_eth_arp_req_to_reply(dev, packet, len); + sandbox_eth_ping_req_to_reply(dev, packet, len); + + return sb_check_ping_reply(dev, packet, len); +} + +static int dm_test_eth_async_ping_reply(struct unit_test_state *uts) +{ + net_ping_ip = string_to_ip("1.1.2.2"); + + sandbox_eth_set_tx_handler(0, sb_with_async_ping_handler); + /* Used by all of the ut_assert macros in the tx_handler */ + sandbox_eth_set_priv(0, uts); + + env_set("ethact", "eth@10002000"); + ut_assertok(net_loop(PING)); + ut_asserteq_str("eth@10002000", env_get("ethact")); + + sandbox_eth_set_tx_handler(0, NULL); + + return 0; +} + +DM_TEST(dm_test_eth_async_ping_reply, UT_TESTF_SCAN_FDT); diff --git a/roms/u-boot/test/dm/fastboot.c b/roms/u-boot/test/dm/fastboot.c new file mode 100644 index 000000000..e7f8c362b --- /dev/null +++ b/roms/u-boot/test/dm/fastboot.c @@ -0,0 +1,95 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2015 Google, Inc + */ + +#include <common.h> +#include <dm.h> +#include <fastboot.h> +#include <fb_mmc.h> +#include <mmc.h> +#include <part.h> +#include <part_efi.h> +#include <dm/test.h> +#include <test/ut.h> +#include <linux/stringify.h> + +#define FB_ALIAS_PREFIX "fastboot_partition_alias_" + +static int dm_test_fastboot_mmc_part(struct unit_test_state *uts) +{ + char response[FASTBOOT_RESPONSE_LEN] = {0}; + char str_disk_guid[UUID_STR_LEN + 1]; + struct blk_desc *mmc_dev_desc, *fb_dev_desc; + struct disk_partition part_info; + struct disk_partition parts[2] = { + { + .start = 48, /* GPT data takes up the first 34 blocks or so */ + .size = 1, + .name = "test1", + }, + { + .start = 49, + .size = 1, + .name = "test2", + }, + }; + + /* + * There are a lot of literal 0s I don't want to have to construct from + * MMC_DEV. + */ + ut_asserteq(0, CONFIG_FASTBOOT_FLASH_MMC_DEV); + ut_assertok(blk_get_device_by_str("mmc", "0", &mmc_dev_desc)); + if (CONFIG_IS_ENABLED(RANDOM_UUID)) { + gen_rand_uuid_str(parts[0].uuid, UUID_STR_FORMAT_STD); + gen_rand_uuid_str(parts[1].uuid, UUID_STR_FORMAT_STD); + gen_rand_uuid_str(str_disk_guid, UUID_STR_FORMAT_STD); + } + ut_assertok(gpt_restore(mmc_dev_desc, str_disk_guid, parts, + ARRAY_SIZE(parts))); + + /* "Classic" partition labels */ + ut_asserteq(1, fastboot_mmc_get_part_info("test1", &fb_dev_desc, + &part_info, response)); + ut_asserteq(2, fastboot_mmc_get_part_info("test2", &fb_dev_desc, + &part_info, response)); + + /* Test aliases */ + ut_assertnull(env_get(FB_ALIAS_PREFIX "test3")); + ut_assertok(env_set(FB_ALIAS_PREFIX "test3", "test1")); + ut_asserteq(1, fastboot_mmc_get_part_info("test3", &fb_dev_desc, + &part_info, response)); + ut_assertok(env_set(FB_ALIAS_PREFIX "test3", NULL)); + + /* "New" partition labels */ + ut_asserteq(1, fastboot_mmc_get_part_info("#test1", &fb_dev_desc, + &part_info, response)); + ut_asserteq(1, fastboot_mmc_get_part_info("0#test1", &fb_dev_desc, + &part_info, response)); + ut_asserteq(1, fastboot_mmc_get_part_info("0.0#test1", &fb_dev_desc, + &part_info, response)); + ut_asserteq(1, fastboot_mmc_get_part_info("0:1", &fb_dev_desc, + &part_info, response)); + ut_asserteq(1, fastboot_mmc_get_part_info("0.0:1", &fb_dev_desc, + &part_info, response)); + ut_asserteq(1, fastboot_mmc_get_part_info("0", &fb_dev_desc, + &part_info, response)); + ut_asserteq(1, fastboot_mmc_get_part_info("0.0", &fb_dev_desc, + &part_info, response)); + ut_asserteq(0, fastboot_mmc_get_part_info("0:0", &fb_dev_desc, + &part_info, response)); + ut_asserteq(0, fastboot_mmc_get_part_info("0.0:0", &fb_dev_desc, + &part_info, response)); + ut_asserteq(0, fastboot_mmc_get_part_info("1", &fb_dev_desc, + &part_info, response)); + ut_asserteq(0, fastboot_mmc_get_part_info("1.0", &fb_dev_desc, + &part_info, response)); + ut_asserteq(1, fastboot_mmc_get_part_info(":1", &fb_dev_desc, + &part_info, response)); + ut_asserteq(0, fastboot_mmc_get_part_info(":0", &fb_dev_desc, + &part_info, response)); + + return 0; +} +DM_TEST(dm_test_fastboot_mmc_part, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); diff --git a/roms/u-boot/test/dm/fdtdec.c b/roms/u-boot/test/dm/fdtdec.c new file mode 100644 index 000000000..1f630ea3e --- /dev/null +++ b/roms/u-boot/test/dm/fdtdec.c @@ -0,0 +1,134 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright 2020 NXP + */ + +#include <common.h> +#include <dm.h> +#include <asm/global_data.h> +#include <dm/of_extra.h> +#include <dm/test.h> +#include <test/ut.h> + +DECLARE_GLOBAL_DATA_PTR; + +static int dm_test_fdtdec_set_carveout(struct unit_test_state *uts) +{ + struct fdt_memory resv; + void *blob; + const fdt32_t *prop; + int blob_sz, len, offset; + + blob_sz = fdt_totalsize(gd->fdt_blob) + 4096; + blob = malloc(blob_sz); + ut_assertnonnull(blob); + + /* Make a writable copy of the fdt blob */ + ut_assertok(fdt_open_into(gd->fdt_blob, blob, blob_sz)); + + resv.start = 0x1000; + resv.end = 0x2000; + ut_assertok(fdtdec_set_carveout(blob, "/a-test", + "memory-region", 2, "test_resv1", + &resv)); + + resv.start = 0x10000; + resv.end = 0x20000; + ut_assertok(fdtdec_set_carveout(blob, "/a-test", + "memory-region", 1, "test_resv2", + &resv)); + + resv.start = 0x100000; + resv.end = 0x200000; + ut_assertok(fdtdec_set_carveout(blob, "/a-test", + "memory-region", 0, "test_resv3", + &resv)); + + offset = fdt_path_offset(blob, "/a-test"); + ut_assert(offset > 0); + prop = fdt_getprop(blob, offset, "memory-region", &len); + ut_assertnonnull(prop); + + ut_asserteq(len, 12); + ut_assert(fdt_node_offset_by_phandle(blob, fdt32_to_cpu(prop[0])) > 0); + ut_assert(fdt_node_offset_by_phandle(blob, fdt32_to_cpu(prop[1])) > 0); + ut_assert(fdt_node_offset_by_phandle(blob, fdt32_to_cpu(prop[2])) > 0); + + free(blob); + + return 0; +} +DM_TEST(dm_test_fdtdec_set_carveout, + UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT | UT_TESTF_FLAT_TREE); + +static int dm_test_fdtdec_add_reserved_memory(struct unit_test_state *uts) +{ + struct fdt_memory resv; + fdt_addr_t addr; + fdt_size_t size; + void *blob; + int blob_sz, parent, subnode; + uint32_t phandle, phandle1; + + blob_sz = fdt_totalsize(gd->fdt_blob) + 128; + blob = malloc(blob_sz); + ut_assertnonnull(blob); + + /* Make a writable copy of the fdt blob */ + ut_assertok(fdt_open_into(gd->fdt_blob, blob, blob_sz)); + + /* Insert a memory region in /reserved-memory node */ + resv.start = 0x1000; + resv.end = 0x1fff; + ut_assertok(fdtdec_add_reserved_memory(blob, "rsvd_region", + &resv, &phandle, false)); + + /* Test /reserve-memory and its subnode should exist */ + parent = fdt_path_offset(blob, "/reserved-memory"); + ut_assert(parent > 0); + subnode = fdt_path_offset(blob, "/reserved-memory/rsvd_region"); + ut_assert(subnode > 0); + + /* Test reg property of /reserved-memory/rsvd_region node */ + addr = fdtdec_get_addr_size_auto_parent(blob, parent, subnode, + "reg", 0, &size, false); + ut_assert(addr == resv.start); + ut_assert(size == resv.end - resv.start + 1); + + /* Insert another memory region in /reserved-memory node */ + subnode = fdt_path_offset(blob, "/reserved-memory/rsvd_region1"); + ut_assert(subnode < 0); + + resv.start = 0x2000; + resv.end = 0x2fff; + ut_assertok(fdtdec_add_reserved_memory(blob, "rsvd_region1", + &resv, &phandle1, true)); + subnode = fdt_path_offset(blob, "/reserved-memory/rsvd_region1"); + ut_assert(subnode > 0); + + /* check that no-map property is present */ + ut_assert(fdt_getprop(blob, subnode, "no-map", NULL) > 0); + + /* phandles must be different */ + ut_assert(phandle != phandle1); + + /* + * Insert a 3rd memory region with the same addr/size as the 1st one, + * but a new node should not be inserted due to the same addr/size. + */ + resv.start = 0x1000; + resv.end = 0x1fff; + ut_assertok(fdtdec_add_reserved_memory(blob, "rsvd_region2", + &resv, &phandle1, false)); + subnode = fdt_path_offset(blob, "/reserved-memory/rsvd_region2"); + ut_assert(subnode < 0); + + /* phandle must be same as the 1st one */ + ut_assert(phandle == phandle1); + + free(blob); + + return 0; +} +DM_TEST(dm_test_fdtdec_add_reserved_memory, + UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT | UT_TESTF_FLAT_TREE); diff --git a/roms/u-boot/test/dm/firmware.c b/roms/u-boot/test/dm/firmware.c new file mode 100644 index 000000000..f37bccfe4 --- /dev/null +++ b/roms/u-boot/test/dm/firmware.c @@ -0,0 +1,23 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2018 Xilinx, Inc. + */ + +#include <common.h> +#include <dm.h> +#include <syscon.h> +#include <asm/test.h> +#include <dm/test.h> +#include <test/test.h> +#include <test/ut.h> + +/* Base test of firmware probe */ +static int dm_test_firmware_probe(struct unit_test_state *uts) +{ + struct udevice *dev; + + ut_assertok(uclass_get_device_by_name(UCLASS_FIRMWARE, + "sandbox-firmware", &dev)); + return 0; +} +DM_TEST(dm_test_firmware_probe, UT_TESTF_SCAN_FDT); diff --git a/roms/u-boot/test/dm/gpio.c b/roms/u-boot/test/dm/gpio.c new file mode 100644 index 000000000..33ae98701 --- /dev/null +++ b/roms/u-boot/test/dm/gpio.c @@ -0,0 +1,780 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2013 Google, Inc + */ + +#include <common.h> +#include <fdtdec.h> +#include <dm.h> +#include <log.h> +#include <malloc.h> +#include <acpi/acpi_device.h> +#include <asm/gpio.h> +#include <dm/device-internal.h> +#include <dm/root.h> +#include <dm/test.h> +#include <dm/util.h> +#include <test/test.h> +#include <test/ut.h> + +/* Test that sandbox GPIOs work correctly */ +static int dm_test_gpio(struct unit_test_state *uts) +{ + unsigned int offset, gpio; + struct dm_gpio_ops *ops; + struct udevice *dev; + struct gpio_desc *desc; + const char *name; + int offset_count; + char buf[80]; + + /* + * We expect to get 4 banks. One is anonymous (just numbered) and + * comes from plat. The other are named a (20 gpios), + * b (10 gpios) and c (10 gpios) and come from the device tree. See + * test/dm/test.dts. + */ + ut_assertok(gpio_lookup_name("b4", &dev, &offset, &gpio)); + ut_asserteq_str(dev->name, "extra-gpios"); + ut_asserteq(4, offset); + ut_asserteq(CONFIG_SANDBOX_GPIO_COUNT + 20 + 4, gpio); + + name = gpio_get_bank_info(dev, &offset_count); + ut_asserteq_str("b", name); + ut_asserteq(10, offset_count); + + /* Get the operations for this device */ + ops = gpio_get_ops(dev); + ut_assert(ops->get_function); + + /* Cannot get a value until it is reserved */ + ut_asserteq(-EBUSY, gpio_get_value(gpio + 1)); + /* + * Now some tests that use the 'sandbox' back door. All GPIOs + * should default to input, include b4 that we are using here. + */ + ut_assertok(gpio_get_status(dev, offset, buf, sizeof(buf))); + ut_asserteq_str("b4: input: 0 [ ]", buf); + + /* Change it to an output */ + sandbox_gpio_set_direction(dev, offset, 1); + ut_assertok(gpio_get_status(dev, offset, buf, sizeof(buf))); + ut_asserteq_str("b4: output: 0 [ ]", buf); + + sandbox_gpio_set_value(dev, offset, 1); + ut_assertok(gpio_get_status(dev, offset, buf, sizeof(buf))); + ut_asserteq_str("b4: output: 1 [ ]", buf); + + ut_assertok(gpio_request(gpio, "testing")); + ut_assertok(gpio_get_status(dev, offset, buf, sizeof(buf))); + ut_asserteq_str("b4: output: 1 [x] testing", buf); + + /* Change the value a bit */ + ut_asserteq(1, ops->get_value(dev, offset)); + ut_assertok(ops->set_value(dev, offset, 0)); + ut_asserteq(0, ops->get_value(dev, offset)); + ut_assertok(gpio_get_status(dev, offset, buf, sizeof(buf))); + ut_asserteq_str("b4: output: 0 [x] testing", buf); + ut_assertok(ops->set_value(dev, offset, 1)); + ut_asserteq(1, ops->get_value(dev, offset)); + + /* Make it an open drain output, and reset it */ + ut_asserteq(GPIOD_IS_OUT | GPIOD_IS_OUT_ACTIVE, + sandbox_gpio_get_flags(dev, offset)); + ut_assertok(ops->set_flags(dev, offset, + GPIOD_IS_OUT | GPIOD_OPEN_DRAIN)); + ut_asserteq(GPIOD_IS_OUT | GPIOD_OPEN_DRAIN, + sandbox_gpio_get_flags(dev, offset)); + ut_assertok(ops->set_flags(dev, offset, + GPIOD_IS_OUT | GPIOD_IS_OUT_ACTIVE)); + ut_asserteq(GPIOD_IS_OUT | GPIOD_IS_OUT_ACTIVE, + sandbox_gpio_get_flags(dev, offset)); + + /* Make it an input */ + ut_assertok(ops->direction_input(dev, offset)); + ut_assertok(gpio_get_status(dev, offset, buf, sizeof(buf))); + ut_asserteq_str("b4: input: 1 [x] testing", buf); + sandbox_gpio_set_value(dev, offset, 0); + ut_asserteq(0, sandbox_gpio_get_value(dev, offset)); + ut_assertok(gpio_get_status(dev, offset, buf, sizeof(buf))); + ut_asserteq_str("b4: input: 0 [x] testing", buf); + + ut_assertok(gpio_free(gpio)); + ut_assertok(gpio_get_status(dev, offset, buf, sizeof(buf))); + ut_asserteq_str("b4: input: 0 [ ]", buf); + + /* Check the 'a' bank also */ + ut_assertok(gpio_lookup_name("a15", &dev, &offset, &gpio)); + ut_asserteq_str(dev->name, "base-gpios"); + ut_asserteq(15, offset); + ut_asserteq(CONFIG_SANDBOX_GPIO_COUNT + 15, gpio); + + name = gpio_get_bank_info(dev, &offset_count); + ut_asserteq_str("a", name); + ut_asserteq(20, offset_count); + + /* add gpio hog tests */ + ut_assertok(gpio_hog_lookup_name("hog_input_active_low", &desc)); + ut_asserteq(GPIOD_IS_IN | GPIOD_ACTIVE_LOW, desc->flags); + ut_asserteq(10, desc->offset); + ut_asserteq(1, dm_gpio_get_value(desc)); + ut_assertok(gpio_hog_lookup_name("hog_input_active_high", &desc)); + ut_asserteq(GPIOD_IS_IN, desc->flags); + ut_asserteq(11, desc->offset); + ut_asserteq(0, dm_gpio_get_value(desc)); + ut_assertok(gpio_hog_lookup_name("hog_output_low", &desc)); + ut_asserteq(GPIOD_IS_OUT, desc->flags); + ut_asserteq(12, desc->offset); + ut_asserteq(0, dm_gpio_get_value(desc)); + ut_assertok(dm_gpio_set_value(desc, 1)); + ut_asserteq(1, dm_gpio_get_value(desc)); + ut_assertok(gpio_hog_lookup_name("hog_output_high", &desc)); + ut_asserteq(GPIOD_IS_OUT, desc->flags); + ut_asserteq(13, desc->offset); + ut_asserteq(1, dm_gpio_get_value(desc)); + ut_assertok(dm_gpio_set_value(desc, 0)); + ut_asserteq(0, dm_gpio_get_value(desc)); + + /* Check if lookup for labels work */ + ut_assertok(gpio_lookup_name("hog_input_active_low", &dev, &offset, + &gpio)); + ut_asserteq_str(dev->name, "base-gpios"); + ut_asserteq(10, offset); + ut_asserteq(CONFIG_SANDBOX_GPIO_COUNT + 10, gpio); + ut_assert(gpio_lookup_name("hog_not_exist", &dev, &offset, + &gpio)); + + return 0; +} +DM_TEST(dm_test_gpio, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); + +/* Test that GPIO open-drain/open-source emulation works correctly */ +static int dm_test_gpio_opendrain_opensource(struct unit_test_state *uts) +{ + struct gpio_desc desc_list[8]; + struct udevice *dev, *gpio_c; + char buf[80]; + + ut_assertok(uclass_get_device(UCLASS_TEST_FDT, 0, &dev)); + ut_asserteq_str("a-test", dev->name); + + ut_assertok(uclass_get_device(UCLASS_GPIO, 3, &gpio_c)); + ut_asserteq_str("pinmux-gpios", gpio_c->name); + + ut_asserteq(8, gpio_request_list_by_name(dev, "test3-gpios", desc_list, + ARRAY_SIZE(desc_list), 0)) + + ut_asserteq(true, !!device_active(gpio_c)); + ut_asserteq_ptr(gpio_c, desc_list[0].dev); + ut_asserteq_ptr(gpio_c, desc_list[1].dev); + ut_asserteq_ptr(gpio_c, desc_list[2].dev); + ut_asserteq_ptr(gpio_c, desc_list[3].dev); + ut_asserteq_ptr(gpio_c, desc_list[4].dev); + ut_asserteq_ptr(gpio_c, desc_list[5].dev); + ut_asserteq_ptr(gpio_c, desc_list[6].dev); + ut_asserteq_ptr(gpio_c, desc_list[7].dev); + + /* GPIO 0 is (GPIO_OUT|GPIO_OPEN_DRAIN) */ + ut_asserteq(GPIOD_IS_OUT | GPIOD_OPEN_DRAIN, + sandbox_gpio_get_flags(gpio_c, 0)); + + /* Set it as output high */ + ut_assertok(dm_gpio_set_value(&desc_list[0], 1)); + ut_asserteq(GPIOD_IS_OUT | GPIOD_OPEN_DRAIN | GPIOD_IS_OUT_ACTIVE, + sandbox_gpio_get_flags(gpio_c, 0)); + + /* Set it as output low */ + ut_assertok(dm_gpio_set_value(&desc_list[0], 0)); + ut_asserteq(GPIOD_IS_OUT | GPIOD_OPEN_DRAIN, + sandbox_gpio_get_flags(gpio_c, 0)); + + /* GPIO 1 is (GPIO_OUT|GPIO_OPEN_SOURCE) */ + ut_asserteq(GPIOD_IS_OUT | GPIOD_OPEN_SOURCE, + sandbox_gpio_get_flags(gpio_c, 1)); + + /* Set it as output high, should become output high */ + ut_assertok(dm_gpio_set_value(&desc_list[1], 1)); + ut_assertok(gpio_get_status(gpio_c, 1, buf, sizeof(buf))); + ut_asserteq_str("c1: output: 1 [x] a-test.test3-gpios1", buf); + + /* Set it as output low */ + ut_assertok(dm_gpio_set_value(&desc_list[1], 0)); + ut_asserteq(GPIOD_IS_OUT | GPIOD_OPEN_SOURCE, + sandbox_gpio_get_flags(gpio_c, 1)); + + ut_assertok(gpio_get_status(gpio_c, 1, buf, sizeof(buf))); + ut_asserteq_str("c1: output: 0 [x] a-test.test3-gpios1", buf); + + /* + * GPIO 6 is (GPIO_ACTIVE_LOW|GPIO_OUT|GPIO_OPEN_DRAIN). Looking at it + * directlt from the driver, we get GPIOD_IS_OUT_ACTIVE also, since it + * is active low + */ + ut_asserteq(GPIOD_ACTIVE_LOW | GPIOD_IS_OUT | GPIOD_OPEN_DRAIN | + GPIOD_IS_OUT_ACTIVE, + sandbox_gpio_get_flags(gpio_c, 6)); + + /* Set it as output high, should become output low */ + ut_assertok(dm_gpio_set_value(&desc_list[6], 1)); + ut_assertok(gpio_get_status(gpio_c, 6, buf, sizeof(buf))); + ut_asserteq_str("c6: output: 0 [x] a-test.test3-gpios6", buf); + + /* Set it as output low */ + ut_assertok(dm_gpio_set_value(&desc_list[6], 0)); + ut_asserteq(GPIOD_ACTIVE_LOW | GPIOD_IS_OUT | GPIOD_OPEN_DRAIN | + GPIOD_IS_OUT_ACTIVE, + sandbox_gpio_get_flags(gpio_c, 6)); + + /* GPIO 7 is (GPIO_ACTIVE_LOW|GPIO_OUT|GPIO_OPEN_SOURCE) */ + ut_asserteq(GPIOD_ACTIVE_LOW | GPIOD_IS_OUT | GPIOD_OPEN_SOURCE | + GPIOD_IS_OUT_ACTIVE, + sandbox_gpio_get_flags(gpio_c, 7)); + + /* Set it as output high */ + ut_assertok(dm_gpio_set_value(&desc_list[7], 1)); + ut_asserteq(GPIOD_ACTIVE_LOW | GPIOD_IS_OUT | GPIOD_OPEN_SOURCE, + sandbox_gpio_get_flags(gpio_c, 7)); + + /* Set it as output low, should become output high */ + ut_assertok(dm_gpio_set_value(&desc_list[7], 0)); + ut_assertok(gpio_get_status(gpio_c, 7, buf, sizeof(buf))); + ut_asserteq_str("c7: output: 1 [x] a-test.test3-gpios7", buf); + + ut_assertok(gpio_free_list(dev, desc_list, 8)); + + return 0; +} +DM_TEST(dm_test_gpio_opendrain_opensource, + UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); + +/* Test that sandbox anonymous GPIOs work correctly */ +static int dm_test_gpio_anon(struct unit_test_state *uts) +{ + unsigned int offset, gpio; + struct udevice *dev; + const char *name; + int offset_count; + + /* And the anonymous bank */ + ut_assertok(gpio_lookup_name("14", &dev, &offset, &gpio)); + ut_asserteq_str(dev->name, "sandbox_gpio"); + ut_asserteq(14, offset); + ut_asserteq(14, gpio); + + name = gpio_get_bank_info(dev, &offset_count); + ut_asserteq_ptr(NULL, name); + ut_asserteq(CONFIG_SANDBOX_GPIO_COUNT, offset_count); + + return 0; +} +DM_TEST(dm_test_gpio_anon, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); + +/* Test that gpio_requestf() works as expected */ +static int dm_test_gpio_requestf(struct unit_test_state *uts) +{ + unsigned int offset, gpio; + struct udevice *dev; + char buf[80]; + + ut_assertok(gpio_lookup_name("b5", &dev, &offset, &gpio)); + ut_assertok(gpio_requestf(gpio, "testing %d %s", 1, "hi")); + sandbox_gpio_set_direction(dev, offset, 1); + sandbox_gpio_set_value(dev, offset, 1); + ut_assertok(gpio_get_status(dev, offset, buf, sizeof(buf))); + ut_asserteq_str("b5: output: 1 [x] testing 1 hi", buf); + + return 0; +} +DM_TEST(dm_test_gpio_requestf, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); + +/* Test that gpio_request() copies its string */ +static int dm_test_gpio_copy(struct unit_test_state *uts) +{ + unsigned int offset, gpio; + struct udevice *dev; + char buf[80], name[10]; + + ut_assertok(gpio_lookup_name("b6", &dev, &offset, &gpio)); + strcpy(name, "odd_name"); + ut_assertok(gpio_request(gpio, name)); + sandbox_gpio_set_direction(dev, offset, 1); + sandbox_gpio_set_value(dev, offset, 1); + ut_assertok(gpio_get_status(dev, offset, buf, sizeof(buf))); + ut_asserteq_str("b6: output: 1 [x] odd_name", buf); + strcpy(name, "nothing"); + ut_assertok(gpio_get_status(dev, offset, buf, sizeof(buf))); + ut_asserteq_str("b6: output: 1 [x] odd_name", buf); + + return 0; +} +DM_TEST(dm_test_gpio_copy, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); + +/* Test that we don't leak memory with GPIOs */ +static int dm_test_gpio_leak(struct unit_test_state *uts) +{ + ut_assertok(dm_test_gpio(uts)); + ut_assertok(dm_test_gpio_anon(uts)); + ut_assertok(dm_test_gpio_requestf(uts)); + ut_assertok(dm_leak_check_end(uts)); + + return 0; +} +DM_TEST(dm_test_gpio_leak, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); + +/* Test that we can find GPIOs using phandles */ +static int dm_test_gpio_phandles(struct unit_test_state *uts) +{ + struct gpio_desc desc, desc_list[8], desc_list2[8]; + struct udevice *dev, *gpio_a, *gpio_b; + + ut_assertok(uclass_get_device(UCLASS_TEST_FDT, 0, &dev)); + ut_asserteq_str("a-test", dev->name); + + ut_assertok(gpio_request_by_name(dev, "test-gpios", 1, &desc, 0)); + ut_assertok(uclass_get_device(UCLASS_GPIO, 1, &gpio_a)); + ut_assertok(uclass_get_device(UCLASS_GPIO, 2, &gpio_b)); + ut_asserteq_str("base-gpios", gpio_a->name); + ut_asserteq(true, !!device_active(gpio_a)); + ut_asserteq_ptr(gpio_a, desc.dev); + ut_asserteq(4, desc.offset); + /* GPIOF_INPUT is the sandbox GPIO driver default */ + ut_asserteq(GPIOF_INPUT, gpio_get_function(gpio_a, 4, NULL)); + ut_assertok(dm_gpio_free(dev, &desc)); + + ut_asserteq(-ENOENT, gpio_request_by_name(dev, "test-gpios", 3, &desc, + 0)); + ut_asserteq_ptr(NULL, desc.dev); + ut_asserteq(desc.offset, 0); + ut_asserteq(-ENOENT, gpio_request_by_name(dev, "test-gpios", 5, &desc, + 0)); + + /* Last GPIO is ignord as it comes after <0> */ + ut_asserteq(3, gpio_request_list_by_name(dev, "test-gpios", desc_list, + ARRAY_SIZE(desc_list), 0)); + ut_asserteq(-EBUSY, gpio_request_list_by_name(dev, "test-gpios", + desc_list2, + ARRAY_SIZE(desc_list2), + 0)); + ut_asserteq(GPIOF_INPUT, gpio_get_function(gpio_a, 4, NULL)); + ut_assertok(gpio_free_list(dev, desc_list, 3)); + ut_asserteq(GPIOF_UNUSED, gpio_get_function(gpio_a, 4, NULL)); + ut_asserteq(3, gpio_request_list_by_name(dev, "test-gpios", desc_list, + ARRAY_SIZE(desc_list), + GPIOD_IS_OUT | + GPIOD_IS_OUT_ACTIVE)); + ut_asserteq(GPIOF_OUTPUT, gpio_get_function(gpio_a, 4, NULL)); + ut_asserteq_ptr(gpio_a, desc_list[0].dev); + ut_asserteq(1, desc_list[0].offset); + ut_asserteq_ptr(gpio_a, desc_list[1].dev); + ut_asserteq(4, desc_list[1].offset); + ut_asserteq_ptr(gpio_b, desc_list[2].dev); + ut_asserteq(5, desc_list[2].offset); + ut_asserteq(1, dm_gpio_get_value(desc_list)); + ut_assertok(gpio_free_list(dev, desc_list, 3)); + + ut_asserteq(GPIOD_IS_OUT | GPIOD_IS_OUT_ACTIVE, + sandbox_gpio_get_flags(gpio_a, 1)); + ut_asserteq(6, gpio_request_list_by_name(dev, "test2-gpios", desc_list, + ARRAY_SIZE(desc_list), 0)); + + /* This was set to output previously but flags resetted to 0 = INPUT */ + ut_asserteq(0, sandbox_gpio_get_flags(gpio_a, 1)); + ut_asserteq(GPIOF_INPUT, gpio_get_function(gpio_a, 1, NULL)); + + /* Active low should invert the input value */ + ut_asserteq(GPIOF_INPUT, gpio_get_function(gpio_b, 6, NULL)); + ut_asserteq(1, dm_gpio_get_value(&desc_list[2])); + + ut_asserteq(GPIOF_INPUT, gpio_get_function(gpio_b, 7, NULL)); + ut_asserteq(GPIOF_OUTPUT, gpio_get_function(gpio_b, 8, NULL)); + ut_asserteq(0, dm_gpio_get_value(&desc_list[4])); + ut_asserteq(GPIOF_OUTPUT, gpio_get_function(gpio_b, 9, NULL)); + ut_asserteq(1, dm_gpio_get_value(&desc_list[5])); + + return 0; +} +DM_TEST(dm_test_gpio_phandles, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); + +/* Check the gpio pin configuration get from device tree information */ +static int dm_test_gpio_get_dir_flags(struct unit_test_state *uts) +{ + struct gpio_desc desc_list[6]; + struct udevice *dev; + ulong flags; + + ut_assertok(uclass_get_device(UCLASS_TEST_FDT, 0, &dev)); + + ut_asserteq(6, gpio_request_list_by_name(dev, "test3-gpios", desc_list, + ARRAY_SIZE(desc_list), 0)); + + ut_assertok(dm_gpio_get_flags(&desc_list[0], &flags)); + ut_asserteq(GPIOD_IS_OUT | GPIOD_OPEN_DRAIN, flags); + + ut_assertok(dm_gpio_get_flags(&desc_list[1], &flags)); + ut_asserteq(GPIOD_IS_OUT | GPIOD_OPEN_SOURCE, flags); + + ut_assertok(dm_gpio_get_flags(&desc_list[2], &flags)); + ut_asserteq(GPIOD_IS_OUT, flags); + + ut_assertok(dm_gpio_get_flags(&desc_list[3], &flags)); + ut_asserteq(GPIOD_IS_IN | GPIOD_PULL_UP, flags); + + ut_assertok(dm_gpio_get_flags(&desc_list[4], &flags)); + ut_asserteq(GPIOD_IS_IN | GPIOD_PULL_DOWN, flags); + + ut_assertok(dm_gpio_get_flags(&desc_list[5], &flags)); + ut_asserteq(GPIOD_IS_IN, flags); + + ut_assertok(gpio_free_list(dev, desc_list, 6)); + + return 0; +} +DM_TEST(dm_test_gpio_get_dir_flags, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); + +/* Test of gpio_get_acpi() */ +static int dm_test_gpio_get_acpi(struct unit_test_state *uts) +{ + struct acpi_gpio agpio; + struct udevice *dev; + struct gpio_desc desc; + + ut_assertok(uclass_get_device(UCLASS_TEST_FDT, 0, &dev)); + ut_asserteq_str("a-test", dev->name); + ut_assertok(gpio_request_by_name(dev, "test-gpios", 1, &desc, 0)); + + /* See sb_gpio_get_acpi() */ + ut_assertok(gpio_get_acpi(&desc, &agpio)); + ut_asserteq(1, agpio.pin_count); + ut_asserteq(4, agpio.pins[0]); + ut_asserteq(ACPI_GPIO_TYPE_IO, agpio.type); + ut_asserteq(ACPI_GPIO_PULL_UP, agpio.pull); + ut_asserteq_str("\\_SB.PINC", agpio.resource); + ut_asserteq(0, agpio.interrupt_debounce_timeout); + ut_asserteq(0, agpio.irq.pin); + ut_asserteq(1234, agpio.output_drive_strength); + ut_asserteq(true, agpio.io_shared); + ut_asserteq(ACPI_GPIO_IO_RESTRICT_INPUT, agpio.io_restrict); + ut_asserteq(ACPI_GPIO_ACTIVE_HIGH, agpio.polarity); + + return 0; +} +DM_TEST(dm_test_gpio_get_acpi, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); + +/* Test of gpio_get_acpi() with an interrupt GPIO */ +static int dm_test_gpio_get_acpi_irq(struct unit_test_state *uts) +{ + struct acpi_gpio agpio; + struct udevice *dev; + struct gpio_desc desc; + + ut_assertok(uclass_get_device(UCLASS_TEST_FDT, 0, &dev)); + ut_asserteq_str("a-test", dev->name); + ut_assertok(gpio_request_by_name(dev, "test2-gpios", 2, &desc, 0)); + + /* See sb_gpio_get_acpi() */ + ut_assertok(gpio_get_acpi(&desc, &agpio)); + ut_asserteq(1, agpio.pin_count); + ut_asserteq(6, agpio.pins[0]); + ut_asserteq(ACPI_GPIO_TYPE_INTERRUPT, agpio.type); + ut_asserteq(ACPI_GPIO_PULL_DOWN, agpio.pull); + ut_asserteq_str("\\_SB.PINC", agpio.resource); + ut_asserteq(4321, agpio.interrupt_debounce_timeout); + ut_asserteq(6, agpio.irq.pin); + ut_asserteq(ACPI_IRQ_ACTIVE_BOTH, agpio.irq.polarity); + ut_asserteq(ACPI_IRQ_SHARED, agpio.irq.shared); + ut_asserteq(true, agpio.irq.wake); + ut_asserteq(0, agpio.output_drive_strength); + ut_asserteq(false, agpio.io_shared); + ut_asserteq(0, agpio.io_restrict); + ut_asserteq(ACPI_GPIO_ACTIVE_LOW, agpio.polarity); + + return 0; +} +DM_TEST(dm_test_gpio_get_acpi_irq, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); + +/* Test that we can get/release GPIOs using managed API */ +static int dm_test_gpio_devm(struct unit_test_state *uts) +{ + static const u32 flags = GPIOD_IS_OUT | GPIOD_IS_OUT_ACTIVE; + struct gpio_desc *desc1, *desc2, *desc3, *desc_err; + struct udevice *dev; + struct udevice *dev2; + + ut_assertok(uclass_get_device_by_name(UCLASS_TEST_FDT, "a-test", + &dev)); + ut_assertok(uclass_get_device_by_name(UCLASS_TEST_FDT, "another-test", + &dev2)); + + /* Get 3 GPIOs from 'a-test' dev */ + desc1 = devm_gpiod_get_index(dev, "test4", 0, flags); + ut_assert(!IS_ERR(desc1)); + desc2 = devm_gpiod_get_index(dev, "test4", 1, flags); + ut_assert(!IS_ERR(desc2)); + desc3 = devm_gpiod_get_index_optional(dev, "test5", 0, flags); + ut_assert(!IS_ERR(desc3)); + ut_assert(desc3); + + /* + * Try get the same 3 GPIOs from 'a-test' and 'another-test' devices. + * check that it fails + */ + desc_err = devm_gpiod_get_index(dev, "test4", 0, flags); + ut_asserteq(-EBUSY, PTR_ERR(desc_err)); + desc_err = devm_gpiod_get_index(dev2, "test4", 0, flags); + ut_asserteq(-EBUSY, PTR_ERR(desc_err)); + desc_err = devm_gpiod_get_index(dev, "test4", 1, flags); + ut_asserteq(-EBUSY, PTR_ERR(desc_err)); + desc_err = devm_gpiod_get_index(dev2, "test4", 1, flags); + ut_asserteq(-EBUSY, PTR_ERR(desc_err)); + desc_err = devm_gpiod_get_index_optional(dev, "test5", 0, flags); + ut_asserteq_ptr(NULL, desc_err); + desc_err = devm_gpiod_get_index_optional(dev2, "test5", 0, flags); + ut_asserteq_ptr(NULL, desc_err); + + /* Try get GPIOs outside of the list */ + desc_err = devm_gpiod_get_index(dev, "test4", 2, flags); + ut_assert(IS_ERR(desc_err)); + desc_err = devm_gpiod_get_index_optional(dev, "test5", 1, flags); + ut_asserteq_ptr(NULL, desc_err); + + /* Manipulate the GPIOs */ + ut_assertok(dm_gpio_set_value(desc1, 1)); + ut_asserteq(1, dm_gpio_get_value(desc1)); + ut_assertok(dm_gpio_set_value(desc1, 0)); + ut_asserteq(0, dm_gpio_get_value(desc1)); + + ut_assertok(dm_gpio_set_value(desc2, 1)); + ut_asserteq(1, dm_gpio_get_value(desc2)); + ut_assertok(dm_gpio_set_value(desc2, 0)); + ut_asserteq(0, dm_gpio_get_value(desc2)); + + ut_assertok(dm_gpio_set_value(desc3, 1)); + ut_asserteq(1, dm_gpio_get_value(desc3)); + ut_assertok(dm_gpio_set_value(desc3, 0)); + ut_asserteq(0, dm_gpio_get_value(desc3)); + + /* Check that the GPIO cannot be owned by more than one device */ + desc_err = devm_gpiod_get_index(dev2, "test4", 0, flags); + ut_asserteq(-EBUSY, PTR_ERR(desc_err)); + desc_err = devm_gpiod_get_index(dev2, "test4", 1, flags); + ut_asserteq(-EBUSY, PTR_ERR(desc_err)); + desc_err = devm_gpiod_get_index_optional(dev2, "test5", 0, flags); + ut_asserteq_ptr(NULL, desc_err); + + /* + * Release one GPIO and check that we can get it back using + * 'another-test' and then 'a-test' + */ + devm_gpiod_put(dev, desc2); + desc2 = devm_gpiod_get_index(dev2, "test4", 1, flags); + ut_assert(!IS_ERR(desc2)); + + devm_gpiod_put(dev2, desc2); + desc2 = devm_gpiod_get_index(dev, "test4", 1, flags); + ut_assert(!IS_ERR(desc2)); + + /* Release one GPIO before removing the 'a-test' dev. */ + devm_gpiod_put(dev, desc2); + device_remove(dev, DM_REMOVE_NORMAL); + + /* All the GPIOs must have been freed. We should be able to claim + * them with the 'another-test' device. + */ + desc1 = devm_gpiod_get_index(dev2, "test4", 0, flags); + ut_assert(!IS_ERR(desc1)); + desc2 = devm_gpiod_get_index(dev2, "test4", 1, flags); + ut_assert(!IS_ERR(desc2)); + desc3 = devm_gpiod_get_index_optional(dev2, "test5", 0, flags); + ut_assert(!IS_ERR(desc3)); + ut_assert(desc3); + + device_remove(dev2, DM_REMOVE_NORMAL); + return 0; +} +DM_TEST(dm_test_gpio_devm, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); + +static int dm_test_clrset_flags(struct unit_test_state *uts) +{ + struct gpio_desc desc; + struct udevice *dev; + ulong flags; + + ut_assertok(uclass_get_device(UCLASS_TEST_FDT, 0, &dev)); + ut_asserteq_str("a-test", dev->name); + ut_assertok(gpio_request_by_name(dev, "test-gpios", 1, &desc, 0)); + + ut_assertok(dm_gpio_clrset_flags(&desc, GPIOD_MASK_DIR, GPIOD_IS_OUT)); + ut_assertok(dm_gpio_get_flags(&desc, &flags)); + ut_asserteq(GPIOD_IS_OUT, flags); + ut_asserteq(GPIOD_IS_OUT, desc.flags); + ut_asserteq(0, sandbox_gpio_get_value(desc.dev, desc.offset)); + + ut_assertok(dm_gpio_clrset_flags(&desc, 0, GPIOD_IS_OUT_ACTIVE)); + ut_assertok(dm_gpio_get_flags(&desc, &flags)); + ut_asserteq(GPIOD_IS_OUT | GPIOD_IS_OUT_ACTIVE, flags); + ut_asserteq(GPIOD_IS_OUT | GPIOD_IS_OUT_ACTIVE, desc.flags); + ut_asserteq(1, sandbox_gpio_get_value(desc.dev, desc.offset)); + ut_asserteq(1, dm_gpio_get_value(&desc)); + + ut_assertok(dm_gpio_clrset_flags(&desc, GPIOD_MASK_DIR, GPIOD_IS_IN)); + ut_assertok(dm_gpio_get_flags(&desc, &flags)); + ut_asserteq(GPIOD_IS_IN, flags & GPIOD_MASK_DIR); + ut_asserteq(GPIOD_IS_IN, desc.flags & GPIOD_MASK_DIR); + + ut_assertok(dm_gpio_clrset_flags(&desc, GPIOD_MASK_PULL, + GPIOD_PULL_UP)); + ut_assertok(dm_gpio_get_flags(&desc, &flags)); + ut_asserteq(GPIOD_IS_IN | GPIOD_PULL_UP, flags); + ut_asserteq(GPIOD_IS_IN | GPIOD_PULL_UP, desc.flags); + + /* Check we cannot set both PULL_UP and PULL_DOWN */ + ut_asserteq(-EINVAL, dm_gpio_clrset_flags(&desc, 0, GPIOD_PULL_DOWN)); + + return 0; +} +DM_TEST(dm_test_clrset_flags, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); + +/* Check that an active-low GPIO works as expected */ +static int dm_test_clrset_flags_invert(struct unit_test_state *uts) +{ + struct gpio_desc desc; + struct udevice *dev; + ulong flags; + + ut_assertok(uclass_get_device(UCLASS_TEST_FDT, 0, &dev)); + ut_asserteq_str("a-test", dev->name); + ut_assertok(gpio_request_by_name(dev, "test-gpios", 1, &desc, + GPIOD_IS_OUT | GPIOD_ACTIVE_LOW)); + + /* + * From this size we see it as 0 (active low), but the sandbox driver + * sees the pin value high + */ + ut_asserteq(0, dm_gpio_get_value(&desc)); + ut_asserteq(1, sandbox_gpio_get_value(desc.dev, desc.offset)); + + ut_assertok(dm_gpio_set_value(&desc, 1)); + ut_asserteq(1, dm_gpio_get_value(&desc)); + ut_asserteq(0, sandbox_gpio_get_value(desc.dev, desc.offset)); + + /* Do the same with dm_gpio_clrset_flags() */ + ut_assertok(dm_gpio_clrset_flags(&desc, GPIOD_IS_OUT_ACTIVE, 0)); + ut_asserteq(0, dm_gpio_get_value(&desc)); + ut_asserteq(1, sandbox_gpio_get_value(desc.dev, desc.offset)); + + ut_assertok(dm_gpio_clrset_flags(&desc, 0, GPIOD_IS_OUT_ACTIVE)); + ut_asserteq(1, dm_gpio_get_value(&desc)); + ut_asserteq(0, sandbox_gpio_get_value(desc.dev, desc.offset)); + + ut_assertok(dm_gpio_get_flags(&desc, &flags)); + ut_asserteq(GPIOD_IS_OUT | GPIOD_ACTIVE_LOW | GPIOD_IS_OUT_ACTIVE, + flags); + ut_asserteq(GPIOD_IS_OUT | GPIOD_ACTIVE_LOW | GPIOD_IS_OUT_ACTIVE, + desc.flags); + + ut_assertok(dm_gpio_clrset_flags(&desc, GPIOD_IS_OUT_ACTIVE, 0)); + ut_assertok(dm_gpio_get_flags(&desc, &flags)); + ut_asserteq(GPIOD_IS_OUT | GPIOD_ACTIVE_LOW, flags); + ut_asserteq(GPIOD_IS_OUT | GPIOD_ACTIVE_LOW, desc.flags); + + return 0; +} +DM_TEST(dm_test_clrset_flags_invert, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); + +static int set_gpios(struct unit_test_state *uts, struct gpio_desc *desc, + int count, uint value) +{ + int i; + + for (i = 0; i < count; i++) { + const uint mask = 1 << i; + + ut_assertok(sandbox_gpio_set_value(desc[i].dev, desc[i].offset, + value & mask)); + } + + return 0; +} + +/* Check that an active-low GPIO works as expected */ +static int dm_test_gpio_get_values_as_int(struct unit_test_state *uts) +{ + const int gpio_count = 3; + struct gpio_desc desc[gpio_count]; + struct udevice *dev; + + ut_assertok(uclass_get_device(UCLASS_TEST_FDT, 0, &dev)); + ut_asserteq_str("a-test", dev->name); + + ut_asserteq(3, gpio_request_list_by_name(dev, "test-gpios", desc, + gpio_count, GPIOD_IS_IN)); + ut_assertok(set_gpios(uts, desc, gpio_count, 0)); + ut_asserteq(0, dm_gpio_get_values_as_int(desc, gpio_count)); + + ut_assertok(set_gpios(uts, desc, gpio_count, 5)); + ut_asserteq(5, dm_gpio_get_values_as_int(desc, gpio_count)); + + ut_assertok(set_gpios(uts, desc, gpio_count, 7)); + ut_asserteq(7, dm_gpio_get_values_as_int(desc, gpio_count)); + + return 0; +} +DM_TEST(dm_test_gpio_get_values_as_int, + UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); + +/* Check that an active-low GPIO works as expected */ +static int dm_test_gpio_get_values_as_int_base3(struct unit_test_state *uts) +{ + const int gpio_count = 3; + struct gpio_desc desc[gpio_count]; + struct udevice *dev; + + ut_assertok(uclass_get_device(UCLASS_TEST_FDT, 0, &dev)); + ut_asserteq_str("a-test", dev->name); + + ut_asserteq(3, gpio_request_list_by_name(dev, "test-gpios", desc, + gpio_count, GPIOD_IS_IN)); + + /* + * First test the sandbox GPIO driver works as expected. The external + * pull resistor should be stronger than the internal one. + */ + sandbox_gpio_set_flags(desc[0].dev, desc[0].offset, + GPIOD_IS_IN | GPIOD_EXT_PULL_UP | GPIOD_PULL_UP); + ut_asserteq(1, dm_gpio_get_value(desc)); + + sandbox_gpio_set_flags(desc[0].dev, desc[0].offset, GPIOD_IS_IN | + GPIOD_EXT_PULL_DOWN | GPIOD_PULL_UP); + ut_asserteq(0, dm_gpio_get_value(desc)); + + sandbox_gpio_set_flags(desc[0].dev, desc[0].offset, + GPIOD_IS_IN | GPIOD_PULL_UP); + ut_asserteq(1, dm_gpio_get_value(desc)); + + sandbox_gpio_set_flags(desc[0].dev, desc[0].offset, GPIOD_PULL_DOWN); + ut_asserteq(0, dm_gpio_get_value(desc)); + + /* + * Set up pins: pull-up (1), pull-down (0) and floating (2). This should + * result in digits 2 0 1, i.e. 2 * 9 + 1 * 3 = 19 + */ + sandbox_gpio_set_flags(desc[0].dev, desc[0].offset, GPIOD_EXT_PULL_UP); + sandbox_gpio_set_flags(desc[1].dev, desc[1].offset, + GPIOD_EXT_PULL_DOWN); + sandbox_gpio_set_flags(desc[2].dev, desc[2].offset, 0); + ut_asserteq(19, dm_gpio_get_values_as_int_base3(desc, gpio_count)); + + /* + * Set up pins: floating (2), pull-up (1) and pull-down (0). This should + * result in digits 0 1 2, i.e. 1 * 3 + 2 = 5 + */ + sandbox_gpio_set_flags(desc[0].dev, desc[0].offset, 0); + sandbox_gpio_set_flags(desc[1].dev, desc[1].offset, GPIOD_EXT_PULL_UP); + sandbox_gpio_set_flags(desc[2].dev, desc[2].offset, + GPIOD_EXT_PULL_DOWN); + ut_asserteq(5, dm_gpio_get_values_as_int_base3(desc, gpio_count)); + + return 0; +} +DM_TEST(dm_test_gpio_get_values_as_int_base3, + UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); diff --git a/roms/u-boot/test/dm/hwspinlock.c b/roms/u-boot/test/dm/hwspinlock.c new file mode 100644 index 000000000..995759d4d --- /dev/null +++ b/roms/u-boot/test/dm/hwspinlock.c @@ -0,0 +1,41 @@ +// SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause +/* + * Copyright (C) 2018, STMicroelectronics - All Rights Reserved + */ + +#include <common.h> +#include <dm.h> +#include <hwspinlock.h> +#include <asm/state.h> +#include <asm/test.h> +#include <dm/test.h> +#include <test/test.h> +#include <test/ut.h> + +/* Test that hwspinlock driver functions are called */ +static int dm_test_hwspinlock_base(struct unit_test_state *uts) +{ + struct sandbox_state *state = state_get_current(); + struct hwspinlock hws; + + ut_assertok(uclass_get_device(UCLASS_HWSPINLOCK, 0, &hws.dev)); + ut_assertnonnull(hws.dev); + ut_asserteq(false, state->hwspinlock); + + hws.id = 0; + ut_assertok(hwspinlock_lock_timeout(&hws, 1)); + ut_asserteq(true, state->hwspinlock); + + ut_assertok(hwspinlock_unlock(&hws)); + ut_asserteq(false, state->hwspinlock); + + ut_assertok(hwspinlock_lock_timeout(&hws, 1)); + ut_assertok(!hwspinlock_lock_timeout(&hws, 1)); + + ut_assertok(hwspinlock_unlock(&hws)); + ut_assertok(!hwspinlock_unlock(&hws)); + + return 0; +} + +DM_TEST(dm_test_hwspinlock_base, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); diff --git a/roms/u-boot/test/dm/i2c.c b/roms/u-boot/test/dm/i2c.c new file mode 100644 index 000000000..d74f5f9fb --- /dev/null +++ b/roms/u-boot/test/dm/i2c.c @@ -0,0 +1,306 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2013 Google, Inc + * + * Note: Test coverage does not include 10-bit addressing + */ + +#include <common.h> +#include <dm.h> +#include <fdtdec.h> +#include <i2c.h> +#include <asm/state.h> +#include <asm/test.h> +#include <dm/device-internal.h> +#include <dm/test.h> +#include <dm/uclass-internal.h> +#include <dm/util.h> +#include <hexdump.h> +#include <test/test.h> +#include <test/ut.h> + +static const int busnum; +static const int chip = 0x2c; + +/* Test that we can find buses and chips */ +static int dm_test_i2c_find(struct unit_test_state *uts) +{ + struct udevice *bus, *dev; + const int no_chip = 0x10; + + /* + * The post_bind() method will bind devices to chip selects. Check + * this then remove the emulation and the slave device. + */ + ut_assertok(uclass_get_device_by_seq(UCLASS_I2C, busnum, &bus)); + ut_assertok(dm_i2c_probe(bus, chip, 0, &dev)); + ut_asserteq(-ENOENT, dm_i2c_probe(bus, no_chip, 0, &dev)); + ut_asserteq(-ENODEV, uclass_get_device_by_seq(UCLASS_I2C, 1, &bus)); + + return 0; +} +DM_TEST(dm_test_i2c_find, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); + +static int dm_test_i2c_read_write(struct unit_test_state *uts) +{ + struct udevice *bus, *dev; + uint8_t buf[5]; + + ut_assertok(uclass_get_device_by_seq(UCLASS_I2C, busnum, &bus)); + ut_assertok(i2c_get_chip(bus, chip, 1, &dev)); + ut_assertok(dm_i2c_read(dev, 0, buf, 5)); + ut_asserteq_mem(buf, "\0\0\0\0\0", sizeof(buf)); + ut_assertok(dm_i2c_write(dev, 2, (uint8_t *)"AB", 2)); + ut_assertok(dm_i2c_read(dev, 0, buf, 5)); + ut_asserteq_mem(buf, "\0\0AB\0", sizeof(buf)); + + return 0; +} +DM_TEST(dm_test_i2c_read_write, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); + +static int dm_test_i2c_speed(struct unit_test_state *uts) +{ + struct udevice *bus, *dev; + uint8_t buf[5]; + + ut_assertok(uclass_get_device_by_seq(UCLASS_I2C, busnum, &bus)); + + /* Use test mode so we create the required errors for invalid speeds */ + sandbox_i2c_set_test_mode(bus, true); + ut_assertok(i2c_get_chip(bus, chip, 1, &dev)); + ut_assertok(dm_i2c_set_bus_speed(bus, 100000)); + ut_assertok(dm_i2c_read(dev, 0, buf, 5)); + ut_assertok(dm_i2c_set_bus_speed(bus, 400000)); + ut_asserteq(400000, dm_i2c_get_bus_speed(bus)); + ut_assertok(dm_i2c_read(dev, 0, buf, 5)); + ut_asserteq(-EINVAL, dm_i2c_write(dev, 0, buf, 5)); + sandbox_i2c_set_test_mode(bus, false); + + return 0; +} +DM_TEST(dm_test_i2c_speed, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); + +static int dm_test_i2c_offset_len(struct unit_test_state *uts) +{ + struct udevice *bus, *dev; + uint8_t buf[5]; + + ut_assertok(uclass_get_device_by_seq(UCLASS_I2C, busnum, &bus)); + ut_assertok(i2c_get_chip(bus, chip, 1, &dev)); + ut_assertok(i2c_set_chip_offset_len(dev, 1)); + ut_assertok(dm_i2c_read(dev, 0, buf, 5)); + + /* This is not supported by the uclass */ + ut_asserteq(-EINVAL, i2c_set_chip_offset_len(dev, 5)); + + return 0; +} +DM_TEST(dm_test_i2c_offset_len, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); + +static int dm_test_i2c_probe_empty(struct unit_test_state *uts) +{ + struct udevice *bus, *dev; + + ut_assertok(uclass_get_device_by_seq(UCLASS_I2C, busnum, &bus)); + + /* Use test mode so that this chip address will always probe */ + sandbox_i2c_set_test_mode(bus, true); + ut_assertok(dm_i2c_probe(bus, SANDBOX_I2C_TEST_ADDR, 0, &dev)); + sandbox_i2c_set_test_mode(bus, false); + + return 0; +} +DM_TEST(dm_test_i2c_probe_empty, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); + +static int dm_test_i2c_bytewise(struct unit_test_state *uts) +{ + struct udevice *bus, *dev; + struct udevice *eeprom; + uint8_t buf[5]; + + ut_assertok(uclass_get_device_by_seq(UCLASS_I2C, busnum, &bus)); + ut_assertok(i2c_get_chip(bus, chip, 1, &dev)); + ut_assertok(dm_i2c_read(dev, 0, buf, 5)); + ut_asserteq_mem(buf, "\0\0\0\0\0", sizeof(buf)); + + /* Tell the EEPROM to only read/write one register at a time */ + ut_assertok(uclass_first_device(UCLASS_I2C_EMUL, &eeprom)); + ut_assertnonnull(eeprom); + sandbox_i2c_eeprom_set_test_mode(eeprom, SIE_TEST_MODE_SINGLE_BYTE); + + /* Now we only get the first byte - the rest will be 0xff */ + ut_assertok(dm_i2c_read(dev, 0, buf, 5)); + ut_asserteq_mem(buf, "\0\xff\xff\xff\xff", sizeof(buf)); + + /* If we do a separate transaction for each byte, it works */ + ut_assertok(i2c_set_chip_flags(dev, DM_I2C_CHIP_RD_ADDRESS)); + ut_assertok(dm_i2c_read(dev, 0, buf, 5)); + ut_asserteq_mem(buf, "\0\0\0\0\0", sizeof(buf)); + + /* This will only write A */ + ut_assertok(i2c_set_chip_flags(dev, 0)); + ut_assertok(dm_i2c_write(dev, 2, (uint8_t *)"AB", 2)); + ut_assertok(dm_i2c_read(dev, 0, buf, 5)); + ut_asserteq_mem(buf, "\0\xff\xff\xff\xff", sizeof(buf)); + + /* Check that the B was ignored */ + ut_assertok(i2c_set_chip_flags(dev, DM_I2C_CHIP_RD_ADDRESS)); + ut_assertok(dm_i2c_read(dev, 0, buf, 5)); + ut_asserteq_mem(buf, "\0\0A\0\0\0", sizeof(buf)); + + /* Now write it again with the new flags, it should work */ + ut_assertok(i2c_set_chip_flags(dev, DM_I2C_CHIP_WR_ADDRESS)); + ut_assertok(dm_i2c_write(dev, 2, (uint8_t *)"AB", 2)); + ut_assertok(dm_i2c_read(dev, 0, buf, 5)); + ut_asserteq_mem(buf, "\0\xff\xff\xff\xff", sizeof(buf)); + + ut_assertok(i2c_set_chip_flags(dev, DM_I2C_CHIP_WR_ADDRESS | + DM_I2C_CHIP_RD_ADDRESS)); + ut_assertok(dm_i2c_read(dev, 0, buf, 5)); + ut_asserteq_mem(buf, "\0\0AB\0\0", sizeof(buf)); + + /* Restore defaults */ + sandbox_i2c_eeprom_set_test_mode(eeprom, SIE_TEST_MODE_NONE); + ut_assertok(i2c_set_chip_flags(dev, 0)); + + return 0; +} +DM_TEST(dm_test_i2c_bytewise, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); + +static int dm_test_i2c_offset(struct unit_test_state *uts) +{ + struct udevice *eeprom; + struct udevice *dev; + uint8_t buf[5]; + + ut_assertok(i2c_get_chip_for_busnum(busnum, chip, 1, &dev)); + + /* Do a transfer so we can find the emulator */ + ut_assertok(dm_i2c_read(dev, 0, buf, 5)); + ut_assertok(uclass_first_device(UCLASS_I2C_EMUL, &eeprom)); + + /* Offset length 0 */ + sandbox_i2c_eeprom_set_offset_len(eeprom, 0); + ut_assertok(i2c_set_chip_offset_len(dev, 0)); + ut_assertok(dm_i2c_write(dev, 10 /* ignored */, (uint8_t *)"AB", 2)); + ut_assertok(dm_i2c_read(dev, 0, buf, 5)); + ut_asserteq_mem("AB\0\0\0\0", buf, sizeof(buf)); + ut_asserteq(0, sanbox_i2c_eeprom_get_prev_offset(eeprom)); + + /* Offset length 1 */ + sandbox_i2c_eeprom_set_offset_len(eeprom, 1); + ut_assertok(i2c_set_chip_offset_len(dev, 1)); + ut_assertok(dm_i2c_write(dev, 2, (uint8_t *)"AB", 2)); + ut_asserteq(2, sanbox_i2c_eeprom_get_prev_offset(eeprom)); + ut_assertok(dm_i2c_read(dev, 0, buf, 5)); + ut_asserteq_mem("ABAB\0", buf, sizeof(buf)); + ut_asserteq(0, sanbox_i2c_eeprom_get_prev_offset(eeprom)); + + /* Offset length 2 boundary - check model wrapping */ + sandbox_i2c_eeprom_set_offset_len(eeprom, 2); + ut_assertok(i2c_set_chip_offset_len(dev, 2)); + ut_assertok(dm_i2c_write(dev, 0xFF, (uint8_t *)"A", 1)); + ut_asserteq(0xFF, sanbox_i2c_eeprom_get_prev_offset(eeprom)); + ut_assertok(dm_i2c_write(dev, 0x100, (uint8_t *)"B", 1)); + ut_asserteq(0x100, sanbox_i2c_eeprom_get_prev_offset(eeprom)); + ut_assertok(dm_i2c_write(dev, 0x101, (uint8_t *)"C", 1)); + ut_asserteq(0x101, sanbox_i2c_eeprom_get_prev_offset(eeprom)); + ut_assertok(dm_i2c_read(dev, 0xFF, buf, 5)); + ut_asserteq_mem("ABCAB", buf, sizeof(buf)); + ut_asserteq(0xFF, sanbox_i2c_eeprom_get_prev_offset(eeprom)); + + /* Offset length 2 */ + sandbox_i2c_eeprom_set_offset_len(eeprom, 2); + ut_assertok(i2c_set_chip_offset_len(dev, 2)); + ut_assertok(dm_i2c_write(dev, 0x2020, (uint8_t *)"AB", 2)); + ut_assertok(dm_i2c_read(dev, 0x2020, buf, 5)); + ut_asserteq_mem("AB\0\0\0", buf, sizeof(buf)); + ut_asserteq(0x2020, sanbox_i2c_eeprom_get_prev_offset(eeprom)); + + /* Offset length 3 */ + sandbox_i2c_eeprom_set_offset_len(eeprom, 3); + ut_assertok(i2c_set_chip_offset_len(dev, 3)); + ut_assertok(dm_i2c_write(dev, 0x303030, (uint8_t *)"AB", 2)); + ut_assertok(dm_i2c_read(dev, 0x303030, buf, 5)); + ut_asserteq_mem("AB\0\0\0", buf, sizeof(buf)); + ut_asserteq(0x303030, sanbox_i2c_eeprom_get_prev_offset(eeprom)); + + /* Offset length 4 */ + sandbox_i2c_eeprom_set_offset_len(eeprom, 4); + ut_assertok(i2c_set_chip_offset_len(dev, 4)); + ut_assertok(dm_i2c_write(dev, 0x40404040, (uint8_t *)"AB", 2)); + ut_assertok(dm_i2c_read(dev, 0x40404040, buf, 5)); + ut_asserteq_mem("AB\0\0\0", buf, sizeof(buf)); + ut_asserteq(0x40404040, sanbox_i2c_eeprom_get_prev_offset(eeprom)); + + /* Restore defaults */ + sandbox_i2c_eeprom_set_offset_len(eeprom, 1); + + return 0; +} +DM_TEST(dm_test_i2c_offset, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); + +static int dm_test_i2c_addr_offset(struct unit_test_state *uts) +{ + struct udevice *eeprom; + struct udevice *dev; + u8 buf[5]; + + ut_assertok(i2c_get_chip_for_busnum(busnum, chip, 1, &dev)); + + /* Do a transfer so we can find the emulator */ + ut_assertok(dm_i2c_read(dev, 0, buf, 5)); + ut_assertok(uclass_first_device(UCLASS_I2C_EMUL, &eeprom)); + + /* Offset length 0 */ + sandbox_i2c_eeprom_set_offset_len(eeprom, 0); + sandbox_i2c_eeprom_set_chip_addr_offset_mask(eeprom, 0x3); + ut_assertok(i2c_set_chip_offset_len(dev, 0)); + ut_assertok(i2c_set_chip_addr_offset_mask(dev, 0x3)); + ut_assertok(dm_i2c_write(dev, 0x3, (uint8_t *)"AB", 2)); + ut_assertok(dm_i2c_read(dev, 0x3, buf, 5)); + ut_asserteq_mem("AB\0\0\0\0", buf, sizeof(buf)); + ut_asserteq(0x3, sanbox_i2c_eeprom_get_prev_offset(eeprom)); + ut_asserteq(chip | 0x3, sanbox_i2c_eeprom_get_prev_addr(eeprom)); + + /* Offset length 1 */ + sandbox_i2c_eeprom_set_offset_len(eeprom, 1); + sandbox_i2c_eeprom_set_chip_addr_offset_mask(eeprom, 0x3); + ut_assertok(i2c_set_chip_offset_len(dev, 1)); + ut_assertok(i2c_set_chip_addr_offset_mask(dev, 0x3)); + ut_assertok(dm_i2c_write(dev, 0x310, (uint8_t *)"AB", 2)); + ut_assertok(dm_i2c_read(dev, 0x310, buf, 5)); + ut_asserteq_mem("AB\0\0\0\0", buf, sizeof(buf)); + ut_asserteq(0x310, sanbox_i2c_eeprom_get_prev_offset(eeprom)); + ut_asserteq(chip | 0x3, sanbox_i2c_eeprom_get_prev_addr(eeprom)); + + /* Offset length 2 */ + sandbox_i2c_eeprom_set_offset_len(eeprom, 2); + sandbox_i2c_eeprom_set_chip_addr_offset_mask(eeprom, 0x3); + ut_assertok(i2c_set_chip_offset_len(dev, 2)); + ut_assertok(i2c_set_chip_addr_offset_mask(dev, 0x3)); + ut_assertok(dm_i2c_write(dev, 0x32020, (uint8_t *)"AB", 2)); + ut_assertok(dm_i2c_read(dev, 0x32020, buf, 5)); + ut_asserteq_mem("AB\0\0\0\0", buf, sizeof(buf)); + ut_asserteq(0x32020, sanbox_i2c_eeprom_get_prev_offset(eeprom)); + ut_asserteq(chip | 0x3, sanbox_i2c_eeprom_get_prev_addr(eeprom)); + + /* Offset length 3 */ + sandbox_i2c_eeprom_set_offset_len(eeprom, 3); + sandbox_i2c_eeprom_set_chip_addr_offset_mask(eeprom, 0x3); + ut_assertok(i2c_set_chip_offset_len(dev, 3)); + ut_assertok(i2c_set_chip_addr_offset_mask(dev, 0x3)); + ut_assertok(dm_i2c_write(dev, 0x3303030, (uint8_t *)"AB", 2)); + ut_assertok(dm_i2c_read(dev, 0x3303030, buf, 5)); + ut_asserteq_mem("AB\0\0\0\0", buf, sizeof(buf)); + ut_asserteq(0x3303030, sanbox_i2c_eeprom_get_prev_offset(eeprom)); + ut_asserteq(chip | 0x3, sanbox_i2c_eeprom_get_prev_addr(eeprom)); + + /* Restore defaults */ + sandbox_i2c_eeprom_set_offset_len(eeprom, 1); + sandbox_i2c_eeprom_set_chip_addr_offset_mask(eeprom, 0); + + return 0; +} + +DM_TEST(dm_test_i2c_addr_offset, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); diff --git a/roms/u-boot/test/dm/i2s.c b/roms/u-boot/test/dm/i2s.c new file mode 100644 index 000000000..c2bf4d560 --- /dev/null +++ b/roms/u-boot/test/dm/i2s.c @@ -0,0 +1,33 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright 2018 Google LLC + * Written by Simon Glass <sjg@chromium.org> + */ + +#include <common.h> +#include <dm.h> +#include <i2s.h> +#include <asm/test.h> +#include <dm/test.h> +#include <test/test.h> +#include <test/ut.h> + +/* Basic test of the i2s codec uclass */ +static int dm_test_i2s(struct unit_test_state *uts) +{ + struct udevice *dev; + u8 data[3]; + + /* check probe success */ + ut_assertok(uclass_first_device_err(UCLASS_I2S, &dev)); + data[0] = 1; + data[1] = 4; + data[2] = 6; + ut_assertok(i2s_tx_data(dev, data, ARRAY_SIZE(data))); + ut_asserteq(11, sandbox_get_i2s_sum(dev)); + ut_assertok(i2s_tx_data(dev, data, 1)); + ut_asserteq(12, sandbox_get_i2s_sum(dev)); + + return 0; +} +DM_TEST(dm_test_i2s, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); diff --git a/roms/u-boot/test/dm/irq.c b/roms/u-boot/test/dm/irq.c new file mode 100644 index 000000000..51dd5e4ab --- /dev/null +++ b/roms/u-boot/test/dm/irq.c @@ -0,0 +1,100 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Test for irq uclass + * + * Copyright 2019 Google LLC + */ + +#include <common.h> +#include <dm.h> +#include <irq.h> +#include <acpi/acpi_device.h> +#include <asm/test.h> +#include <dm/test.h> +#include <test/ut.h> + +/* Base test of the irq uclass */ +static int dm_test_irq_base(struct unit_test_state *uts) +{ + struct udevice *dev; + + ut_assertok(uclass_first_device_err(UCLASS_IRQ, &dev)); + + ut_asserteq(5, irq_route_pmc_gpio_gpe(dev, 4)); + ut_asserteq(-ENOENT, irq_route_pmc_gpio_gpe(dev, 14)); + + ut_assertok(irq_set_polarity(dev, 4, true)); + ut_asserteq(-EINVAL, irq_set_polarity(dev, 14, true)); + + ut_assertok(irq_snapshot_polarities(dev)); + ut_assertok(irq_restore_polarities(dev)); + + return 0; +} +DM_TEST(dm_test_irq_base, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); + +/* Test of irq_first_device_type() */ +static int dm_test_irq_type(struct unit_test_state *uts) +{ + struct udevice *dev; + + ut_assertok(irq_first_device_type(SANDBOX_IRQT_BASE, &dev)); + ut_asserteq(-ENODEV, irq_first_device_type(X86_IRQT_BASE, &dev)); + + return 0; +} +DM_TEST(dm_test_irq_type, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); + +/* Test of irq_read_and_clear() */ +static int dm_test_read_and_clear(struct unit_test_state *uts) +{ + struct irq irq; + + ut_assertok(irq_first_device_type(SANDBOX_IRQT_BASE, &irq.dev)); + irq.id = SANDBOX_IRQN_PEND; + ut_asserteq(0, irq_read_and_clear(&irq)); + ut_asserteq(0, irq_read_and_clear(&irq)); + ut_asserteq(0, irq_read_and_clear(&irq)); + ut_asserteq(1, irq_read_and_clear(&irq)); + ut_asserteq(0, irq_read_and_clear(&irq)); + + return 0; +} +DM_TEST(dm_test_read_and_clear, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); + +/* Test of irq_request() */ +static int dm_test_request(struct unit_test_state *uts) +{ + struct udevice *dev; + struct irq irq; + + ut_assertok(uclass_first_device_err(UCLASS_TEST_FDT, &dev)); + ut_asserteq_str("a-test", dev->name); + ut_assertok(irq_get_by_index(dev, 0, &irq)); + ut_asserteq(3, irq.id); + + return 0; +} +DM_TEST(dm_test_request, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); + +/* Test of irq_get_acpi() */ +static int dm_test_irq_get_acpi(struct unit_test_state *uts) +{ + struct acpi_irq airq; + struct udevice *dev; + struct irq irq; + + ut_assertok(uclass_first_device_err(UCLASS_TEST_FDT, &dev)); + ut_assertok(irq_get_by_index(dev, 0, &irq)); + + /* see sandbox_get_acpi() */ + ut_assertok(irq_get_acpi(&irq, &airq)); + ut_asserteq(3, airq.pin); + ut_asserteq(ACPI_IRQ_LEVEL_TRIGGERED, airq.mode); + ut_asserteq(ACPI_IRQ_ACTIVE_HIGH, airq.polarity); + ut_asserteq(ACPI_IRQ_SHARED, airq.shared); + ut_asserteq(ACPI_IRQ_WAKE, airq.wake); + + return 0; +} +DM_TEST(dm_test_irq_get_acpi, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); diff --git a/roms/u-boot/test/dm/k210_pll.c b/roms/u-boot/test/dm/k210_pll.c new file mode 100644 index 000000000..54764f269 --- /dev/null +++ b/roms/u-boot/test/dm/k210_pll.c @@ -0,0 +1,96 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2020 Sean Anderson <seanga2@gmail.com> + */ + +#include <common.h> +/* For DIV_ROUND_DOWN_ULL, defined in linux/kernel.h */ +#include <div64.h> +#include <dm/test.h> +#include <kendryte/pll.h> +#include <test/ut.h> + +static int dm_test_k210_pll_calc_config(u32 rate, u32 rate_in, + struct k210_pll_config *best) +{ + u64 f, r, od, max_r, inv_ratio; + s64 error, best_error; + + best_error = S64_MAX; + error = best_error; + max_r = min(16ULL, DIV_ROUND_DOWN_ULL(rate_in, 13300000)); + inv_ratio = DIV_ROUND_CLOSEST_ULL((u64)rate_in << 32, rate); + + /* Brute force it */ + for (r = 1; r <= max_r; r++) { + for (f = 1; f <= 64; f++) { + for (od = 1; od <= 16; od++) { + u64 vco = DIV_ROUND_CLOSEST_ULL(rate_in * f, r); + + if (vco > 1750000000 || vco < 340000000) + continue; + + error = DIV_ROUND_CLOSEST_ULL(f * inv_ratio, + r * od); + /* The lower 16 bits are spurious */ + error = abs((error - BIT(32))) >> 16; + if (error < best_error) { + best->r = r; + best->f = f; + best->od = od; + best_error = error; + } + } + } + } + + if (best_error == S64_MAX) + return -EINVAL; + return 0; +} + +static int dm_test_k210_pll_compare(struct k210_pll_config *ours, + struct k210_pll_config *theirs) +{ + return (u32)ours->f * theirs->r * theirs->od != + (u32)theirs->f * ours->r * ours->od; +} + +static int dm_test_k210_pll(struct unit_test_state *uts) +{ + struct k210_pll_config ours, theirs; + + /* General range checks */ + ut_asserteq(-EINVAL, k210_pll_calc_config(0, 26000000, &theirs)); + ut_asserteq(-EINVAL, k210_pll_calc_config(390000000, 0, &theirs)); + ut_asserteq(-EINVAL, k210_pll_calc_config(2000000000, 26000000, + &theirs)); + ut_asserteq(-EINVAL, k210_pll_calc_config(390000000, 2000000000, + &theirs)); + ut_asserteq(-EINVAL, k210_pll_calc_config(1500000000, 20000000, + &theirs)); + + /* Verify we get the same output with brute-force */ + ut_assertok(dm_test_k210_pll_calc_config(390000000, 26000000, &ours)); + ut_assertok(k210_pll_calc_config(390000000, 26000000, &theirs)); + ut_assertok(dm_test_k210_pll_compare(&ours, &theirs)); + + ut_assertok(dm_test_k210_pll_calc_config(26000000, 390000000, &ours)); + ut_assertok(k210_pll_calc_config(26000000, 390000000, &theirs)); + ut_assertok(dm_test_k210_pll_compare(&ours, &theirs)); + + ut_assertok(dm_test_k210_pll_calc_config(400000000, 26000000, &ours)); + ut_assertok(k210_pll_calc_config(400000000, 26000000, &theirs)); + ut_assertok(dm_test_k210_pll_compare(&ours, &theirs)); + + ut_assertok(dm_test_k210_pll_calc_config(27000000, 26000000, &ours)); + ut_assertok(k210_pll_calc_config(27000000, 26000000, &theirs)); + ut_assertok(dm_test_k210_pll_compare(&ours, &theirs)); + + ut_assertok(dm_test_k210_pll_calc_config(26000000, 27000000, &ours)); + ut_assertok(k210_pll_calc_config(26000000, 27000000, &theirs)); + ut_assertok(dm_test_k210_pll_compare(&ours, &theirs)); + + return 0; +} +DM_TEST(dm_test_k210_pll, 0); diff --git a/roms/u-boot/test/dm/led.c b/roms/u-boot/test/dm/led.c new file mode 100644 index 000000000..ac6ee3639 --- /dev/null +++ b/roms/u-boot/test/dm/led.c @@ -0,0 +1,144 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2015 Google, Inc + */ + +#include <common.h> +#include <dm.h> +#include <led.h> +#include <asm/gpio.h> +#include <dm/test.h> +#include <test/test.h> +#include <test/ut.h> + +/* Base test of the led uclass */ +static int dm_test_led_base(struct unit_test_state *uts) +{ + struct udevice *dev; + + /* Get the top-level device */ + ut_assertok(uclass_get_device(UCLASS_LED, 0, &dev)); + ut_assertok(uclass_get_device(UCLASS_LED, 1, &dev)); + ut_assertok(uclass_get_device(UCLASS_LED, 2, &dev)); + ut_assertok(uclass_get_device(UCLASS_LED, 3, &dev)); + ut_assertok(uclass_get_device(UCLASS_LED, 4, &dev)); + ut_asserteq(-ENODEV, uclass_get_device(UCLASS_LED, 5, &dev)); + + return 0; +} +DM_TEST(dm_test_led_base, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); + +/* Test of the LED 'default-state' device tree property */ +static int dm_test_led_default_state(struct unit_test_state *uts) +{ + struct udevice *dev; + + /* configure the default state (auto-probe) */ + led_default_state(); + + /* Check that we handle the default-state property correctly. */ + ut_assertok(led_get_by_label("sandbox:default_on", &dev)); + ut_asserteq(LEDST_ON, led_get_state(dev)); + + /* Also tests default label behaviour */ + ut_assertok(led_get_by_label("default_off", &dev)); + ut_asserteq(LEDST_OFF, led_get_state(dev)); + + return 0; +} +DM_TEST(dm_test_led_default_state, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); + +/* Test of the led uclass using the led_gpio driver */ +static int dm_test_led_gpio(struct unit_test_state *uts) +{ + const int offset = 1; + struct udevice *dev, *gpio; + + /* + * Check that we can manipulate an LED. LED 1 is connected to GPIO + * bank gpio_a, offset 1. + */ + ut_assertok(uclass_get_device(UCLASS_LED, 1, &dev)); + ut_assertok(uclass_get_device(UCLASS_GPIO, 1, &gpio)); + ut_asserteq(0, sandbox_gpio_get_value(gpio, offset)); + ut_assertok(led_set_state(dev, LEDST_ON)); + ut_asserteq(1, sandbox_gpio_get_value(gpio, offset)); + ut_asserteq(LEDST_ON, led_get_state(dev)); + + ut_assertok(led_set_state(dev, LEDST_OFF)); + ut_asserteq(0, sandbox_gpio_get_value(gpio, offset)); + ut_asserteq(LEDST_OFF, led_get_state(dev)); + + return 0; +} +DM_TEST(dm_test_led_gpio, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); + +/* Test that we can toggle LEDs */ +static int dm_test_led_toggle(struct unit_test_state *uts) +{ + const int offset = 1; + struct udevice *dev, *gpio; + + /* + * Check that we can manipulate an LED. LED 1 is connected to GPIO + * bank gpio_a, offset 1. + */ + ut_assertok(uclass_get_device(UCLASS_LED, 1, &dev)); + ut_assertok(uclass_get_device(UCLASS_GPIO, 1, &gpio)); + ut_asserteq(0, sandbox_gpio_get_value(gpio, offset)); + ut_assertok(led_set_state(dev, LEDST_TOGGLE)); + ut_asserteq(1, sandbox_gpio_get_value(gpio, offset)); + ut_asserteq(LEDST_ON, led_get_state(dev)); + + ut_assertok(led_set_state(dev, LEDST_TOGGLE)); + ut_asserteq(0, sandbox_gpio_get_value(gpio, offset)); + ut_asserteq(LEDST_OFF, led_get_state(dev)); + + return 0; +} +DM_TEST(dm_test_led_toggle, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); + +/* Test obtaining an LED by label */ +static int dm_test_led_label(struct unit_test_state *uts) +{ + struct udevice *dev, *cmp; + + ut_assertok(led_get_by_label("sandbox:red", &dev)); + ut_asserteq(1, device_active(dev)); + ut_assertok(uclass_get_device(UCLASS_LED, 1, &cmp)); + ut_asserteq_ptr(dev, cmp); + + ut_assertok(led_get_by_label("sandbox:green", &dev)); + ut_asserteq(1, device_active(dev)); + ut_assertok(uclass_get_device(UCLASS_LED, 2, &cmp)); + ut_asserteq_ptr(dev, cmp); + + ut_asserteq(-ENODEV, led_get_by_label("sandbox:blue", &dev)); + + return 0; +} +DM_TEST(dm_test_led_label, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); + +/* Test LED blinking */ +#ifdef CONFIG_LED_BLINK +static int dm_test_led_blink(struct unit_test_state *uts) +{ + const int offset = 1; + struct udevice *dev, *gpio; + + /* + * Check that we get an error when trying to blink an LED, since it is + * not supported by the GPIO LED driver. + */ + ut_assertok(uclass_get_device(UCLASS_LED, 1, &dev)); + ut_assertok(uclass_get_device(UCLASS_GPIO, 1, &gpio)); + ut_asserteq(0, sandbox_gpio_get_value(gpio, offset)); + ut_asserteq(-ENOSYS, led_set_state(dev, LEDST_BLINK)); + ut_asserteq(0, sandbox_gpio_get_value(gpio, offset)); + ut_asserteq(LEDST_OFF, led_get_state(dev)); + ut_asserteq(-ENOSYS, led_set_period(dev, 100)); + + return 0; +} +DM_TEST(dm_test_led_blink, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); +#endif diff --git a/roms/u-boot/test/dm/mailbox.c b/roms/u-boot/test/dm/mailbox.c new file mode 100644 index 000000000..7ad8a1cbb --- /dev/null +++ b/roms/u-boot/test/dm/mailbox.c @@ -0,0 +1,32 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2016, NVIDIA CORPORATION. + */ + +#include <common.h> +#include <dm.h> +#include <malloc.h> +#include <dm/test.h> +#include <asm/mbox.h> +#include <test/test.h> +#include <test/ut.h> + +static int dm_test_mailbox(struct unit_test_state *uts) +{ + struct udevice *dev; + uint32_t msg; + + ut_assertok(uclass_get_device_by_name(UCLASS_MISC, "mbox-test", &dev)); + ut_assertok(sandbox_mbox_test_get(dev)); + + ut_asserteq(-ETIMEDOUT, sandbox_mbox_test_recv(dev, &msg)); + ut_assertok(sandbox_mbox_test_send(dev, 0xaaff9955UL)); + ut_assertok(sandbox_mbox_test_recv(dev, &msg)); + ut_asserteq(msg, 0xaaff9955UL ^ SANDBOX_MBOX_PING_XOR); + ut_asserteq(-ETIMEDOUT, sandbox_mbox_test_recv(dev, &msg)); + + ut_assertok(sandbox_mbox_test_free(dev)); + + return 0; +} +DM_TEST(dm_test_mailbox, UT_TESTF_SCAN_FDT); diff --git a/roms/u-boot/test/dm/mdio.c b/roms/u-boot/test/dm/mdio.c new file mode 100644 index 000000000..64347e127 --- /dev/null +++ b/roms/u-boot/test/dm/mdio.c @@ -0,0 +1,58 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * (C) Copyright 2019 + * Alex Marginean, NXP + */ + +#include <common.h> +#include <dm.h> +#include <log.h> +#include <miiphy.h> +#include <misc.h> +#include <dm/test.h> +#include <test/test.h> +#include <test/ut.h> + +/* macros copied over from mdio_sandbox.c */ +#define SANDBOX_PHY_ADDR 5 +#define SANDBOX_PHY_REG_CNT 2 + +/* test using 1st register, 0 */ +#define SANDBOX_PHY_REG 0 + +#define TEST_REG_VALUE 0xabcd + +static int dm_test_mdio(struct unit_test_state *uts) +{ + struct uclass *uc; + struct udevice *dev; + struct mdio_ops *ops; + u16 reg; + + ut_assertok(uclass_get(UCLASS_MDIO, &uc)); + + ut_assertok(uclass_get_device_by_name(UCLASS_MDIO, "mdio-test", &dev)); + + ops = mdio_get_ops(dev); + ut_assertnonnull(ops); + ut_assertnonnull(ops->read); + ut_assertnonnull(ops->write); + + ut_assertok(ops->write(dev, SANDBOX_PHY_ADDR, MDIO_DEVAD_NONE, + SANDBOX_PHY_REG, TEST_REG_VALUE)); + reg = ops->read(dev, SANDBOX_PHY_ADDR, MDIO_DEVAD_NONE, + SANDBOX_PHY_REG); + ut_asserteq(reg, TEST_REG_VALUE); + + ut_assert(ops->read(dev, SANDBOX_PHY_ADDR + 1, MDIO_DEVAD_NONE, + SANDBOX_PHY_REG) != 0); + + ut_assertok(ops->reset(dev)); + reg = ops->read(dev, SANDBOX_PHY_ADDR, MDIO_DEVAD_NONE, + SANDBOX_PHY_REG); + ut_asserteq(reg, 0); + + return 0; +} + +DM_TEST(dm_test_mdio, UT_TESTF_SCAN_FDT); diff --git a/roms/u-boot/test/dm/mdio_mux.c b/roms/u-boot/test/dm/mdio_mux.c new file mode 100644 index 000000000..950f385d1 --- /dev/null +++ b/roms/u-boot/test/dm/mdio_mux.c @@ -0,0 +1,81 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * (C) Copyright 2019 + * Alex Marginean, NXP + */ + +#include <common.h> +#include <dm.h> +#include <miiphy.h> +#include <misc.h> +#include <dm/test.h> +#include <test/test.h> +#include <test/ut.h> + +/* macros copied over from mdio_sandbox.c */ +#define SANDBOX_PHY_ADDR 5 +#define SANDBOX_PHY_REG_CNT 2 + +#define TEST_REG_VALUE 0xabcd + +static int dm_test_mdio_mux(struct unit_test_state *uts) +{ + struct uclass *uc; + struct udevice *mux; + struct udevice *mdio_ch0, *mdio_ch1, *mdio; + struct mdio_ops *ops, *ops_parent; + struct mdio_mux_ops *mmops; + u16 reg; + + ut_assertok(uclass_get(UCLASS_MDIO_MUX, &uc)); + + ut_assertok(uclass_get_device_by_name(UCLASS_MDIO_MUX, "mdio-mux-test", + &mux)); + + ut_assertok(uclass_get_device_by_name(UCLASS_MDIO, "mdio-ch-test@0", + &mdio_ch0)); + ut_assertok(uclass_get_device_by_name(UCLASS_MDIO, "mdio-ch-test@1", + &mdio_ch1)); + + ut_assertok(uclass_get_device_by_name(UCLASS_MDIO, "mdio-test", &mdio)); + + ops = mdio_get_ops(mdio_ch0); + ut_assertnonnull(ops); + ut_assertnonnull(ops->read); + ut_assertnonnull(ops->write); + + mmops = mdio_mux_get_ops(mux); + ut_assertnonnull(mmops); + ut_assertnonnull(mmops->select); + + ops_parent = mdio_get_ops(mdio); + ut_assertnonnull(ops); + ut_assertnonnull(ops->read); + + /* + * mux driver sets last register on the emulated PHY whenever a group + * is selected to the selection #. Just reading that register from + * either of the child buses should return the id of the child bus + */ + reg = ops->read(mdio_ch0, SANDBOX_PHY_ADDR, MDIO_DEVAD_NONE, + SANDBOX_PHY_REG_CNT - 1); + ut_asserteq(reg, 0); + + reg = ops->read(mdio_ch1, SANDBOX_PHY_ADDR, MDIO_DEVAD_NONE, + SANDBOX_PHY_REG_CNT - 1); + ut_asserteq(reg, 1); + + mmops->select(mux, MDIO_MUX_SELECT_NONE, 5); + reg = ops_parent->read(mdio, SANDBOX_PHY_ADDR, MDIO_DEVAD_NONE, + SANDBOX_PHY_REG_CNT - 1); + ut_asserteq(reg, 5); + + mmops->deselect(mux, 5); + reg = ops_parent->read(mdio, SANDBOX_PHY_ADDR, MDIO_DEVAD_NONE, + SANDBOX_PHY_REG_CNT - 1); + ut_asserteq(reg, (u16)MDIO_MUX_SELECT_NONE); + + return 0; +} + +DM_TEST(dm_test_mdio_mux, UT_TESTF_SCAN_FDT); diff --git a/roms/u-boot/test/dm/misc.c b/roms/u-boot/test/dm/misc.c new file mode 100644 index 000000000..1506fdefe --- /dev/null +++ b/roms/u-boot/test/dm/misc.c @@ -0,0 +1,84 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * (C) Copyright 2018 + * Mario Six, Guntermann & Drunck GmbH, mario.six@gdsys.cc + */ + +#include <common.h> +#include <dm.h> +#include <dm/test.h> +#include <misc.h> +#include <test/test.h> +#include <test/ut.h> + +static int dm_test_misc(struct unit_test_state *uts) +{ + struct udevice *dev; + u8 buf[16]; + int id; + ulong last_ioctl; + bool enabled; + + ut_assertok(uclass_get_device_by_name(UCLASS_MISC, "misc-test", &dev)); + + /* Read / write tests */ + ut_asserteq(4, misc_write(dev, 0, "TEST", 4)); + ut_asserteq(5, misc_write(dev, 4, "WRITE", 5)); + ut_asserteq(9, misc_read(dev, 0, buf, 9)); + + ut_asserteq_mem(buf, "TESTWRITE", 9); + + /* Call tests */ + + id = 0; + ut_assertok(misc_call(dev, 0, &id, 4, buf, 16)); + ut_asserteq_mem(buf, "Zero", 4); + + id = 2; + ut_assertok(misc_call(dev, 0, &id, 4, buf, 16)); + ut_asserteq_mem(buf, "Two", 3); + + ut_assertok(misc_call(dev, 1, &id, 4, buf, 16)); + ut_asserteq_mem(buf, "Forty-two", 9); + + id = 1; + ut_assertok(misc_call(dev, 1, &id, 4, buf, 16)); + ut_asserteq_mem(buf, "Forty-one", 9); + + /* IOCTL tests */ + + ut_assertok(misc_ioctl(dev, 6, NULL)); + /* Read back last issued ioctl */ + ut_assertok(misc_call(dev, 2, NULL, 0, &last_ioctl, + sizeof(last_ioctl))); + ut_asserteq(6, last_ioctl) + + ut_assertok(misc_ioctl(dev, 23, NULL)); + /* Read back last issued ioctl */ + ut_assertok(misc_call(dev, 2, NULL, 0, &last_ioctl, + sizeof(last_ioctl))); + ut_asserteq(23, last_ioctl) + + /* Enable / disable tests */ + + /* Read back enable/disable status */ + ut_assertok(misc_call(dev, 3, NULL, 0, &enabled, + sizeof(enabled))); + ut_asserteq(true, enabled); + + ut_assertok(misc_set_enabled(dev, false)); + /* Read back enable/disable status */ + ut_assertok(misc_call(dev, 3, NULL, 0, &enabled, + sizeof(enabled))); + ut_asserteq(false, enabled); + + ut_assertok(misc_set_enabled(dev, true)); + /* Read back enable/disable status */ + ut_assertok(misc_call(dev, 3, NULL, 0, &enabled, + sizeof(enabled))); + ut_asserteq(true, enabled); + + return 0; +} + +DM_TEST(dm_test_misc, UT_TESTF_SCAN_FDT); diff --git a/roms/u-boot/test/dm/mmc.c b/roms/u-boot/test/dm/mmc.c new file mode 100644 index 000000000..f744452ff --- /dev/null +++ b/roms/u-boot/test/dm/mmc.c @@ -0,0 +1,54 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2015 Google, Inc + */ + +#include <common.h> +#include <dm.h> +#include <mmc.h> +#include <part.h> +#include <dm/test.h> +#include <test/test.h> +#include <test/ut.h> + +/* + * Basic test of the mmc uclass. We could expand this by implementing an MMC + * stack for sandbox, or at least implementing the basic operation. + */ +static int dm_test_mmc_base(struct unit_test_state *uts) +{ + struct udevice *dev; + + ut_assertok(uclass_get_device(UCLASS_MMC, 0, &dev)); + + return 0; +} +DM_TEST(dm_test_mmc_base, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); + +static int dm_test_mmc_blk(struct unit_test_state *uts) +{ + struct udevice *dev; + struct blk_desc *dev_desc; + int i; + char write[1024], read[1024]; + + ut_assertok(uclass_get_device(UCLASS_MMC, 0, &dev)); + ut_assertok(blk_get_device_by_str("mmc", "0", &dev_desc)); + + /* Write a few blocks and verify that we get the same data back */ + ut_asserteq(512, dev_desc->blksz); + for (i = 0; i < sizeof(write); i++) + write[i] = i; + ut_asserteq(2, blk_dwrite(dev_desc, 0, 2, write)); + ut_asserteq(2, blk_dread(dev_desc, 0, 2, read)); + ut_asserteq_mem(write, read, sizeof(write)); + + /* Now erase them */ + memset(write, '\0', sizeof(write)); + ut_asserteq(2, blk_derase(dev_desc, 0, 2)); + ut_asserteq(2, blk_dread(dev_desc, 0, 2, read)); + ut_asserteq_mem(write, read, sizeof(write)); + + return 0; +} +DM_TEST(dm_test_mmc_blk, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); diff --git a/roms/u-boot/test/dm/mux-cmd.c b/roms/u-boot/test/dm/mux-cmd.c new file mode 100644 index 000000000..11c237b5d --- /dev/null +++ b/roms/u-boot/test/dm/mux-cmd.c @@ -0,0 +1,177 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2020 Texas Instruments Inc. + * Pratyush Yadav <p.yadav@ti.com> + */ +#include <common.h> +#include <dm.h> +#include <mux.h> +#include <mux-internal.h> +#include <dt-bindings/mux/mux.h> +#include <asm/test.h> +#include <dm/test.h> +#include <test/ut.h> +#include <console.h> +#include <rand.h> + +#define BUF_SIZE 256 + +/* Test 'mux list' */ +static int dm_test_cmd_mux_list(struct unit_test_state *uts) +{ + char str[BUF_SIZE], *tok; + struct udevice *dev; + struct mux_chip *chip; + struct mux_control *mux; + int i; + unsigned long val; + + sandbox_set_enable_memio(true); + + ut_assertok(uclass_get_device_by_name(UCLASS_MUX, "a-mux-controller", + &dev)); + chip = dev_get_uclass_priv(dev); + ut_assertnonnull(chip); + + run_command("mux list", 0); + ut_assert_nextline("a-mux-controller:"); + + /* + * Check the table header to make sure we are not out of sync with the + * code in the command. If we are, catch it early. + */ + console_record_readline(str, BUF_SIZE); + tok = strtok(str, " "); + ut_asserteq_str("ID", tok); + + tok = strtok(NULL, " "); + ut_asserteq_str("Selected", tok); + + tok = strtok(NULL, " "); + ut_asserteq_str("Current", tok); + tok = strtok(NULL, " "); + ut_asserteq_str("State", tok); + + tok = strtok(NULL, " "); + ut_asserteq_str("Idle", tok); + tok = strtok(NULL, " "); + ut_asserteq_str("State", tok); + + tok = strtok(NULL, " "); + ut_asserteq_str("Num", tok); + tok = strtok(NULL, " "); + ut_asserteq_str("States", tok); + + for (i = 0; i < chip->controllers; i++) { + mux = &chip->mux[i]; + + console_record_readline(str, BUF_SIZE); + + /* + * Check if the ID printed matches with the ID of the chip we + * have. + */ + tok = strtok(str, " "); + ut_assertok(strict_strtoul(tok, 10, &val)); + ut_asserteq(i, val); + + /* Check if mux selection state matches. */ + tok = strtok(NULL, " "); + if (mux->in_use) { + ut_asserteq_str("yes", tok); + } else { + ut_asserteq_str("no", tok); + } + + /* Check if the current state matches. */ + tok = strtok(NULL, " "); + if (mux->cached_state == MUX_IDLE_AS_IS) { + ut_asserteq_str("unknown", tok); + } else { + ut_assertok(strict_strtoul(tok, 16, &val)); + ut_asserteq(mux->cached_state, val); + } + + /* Check if the idle state matches */ + tok = strtok(NULL, " "); + if (mux->idle_state == MUX_IDLE_AS_IS) { + ut_asserteq_str("as-is", tok); + } else { + ut_assertok(strict_strtoul(tok, 16, &val)); + ut_asserteq(mux->idle_state, val); + } + + /* Check if the number of states matches */ + tok = strtok(NULL, " "); + ut_assertok(strict_strtoul(tok, 16, &val)); + ut_asserteq(mux->states, val); + } + + return 0; +} +DM_TEST(dm_test_cmd_mux_list, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); + +static int dm_test_cmd_mux_select(struct unit_test_state *uts) +{ + struct udevice *dev; + struct mux_chip *chip; + struct mux_control *mux; + char cmd[BUF_SIZE]; + unsigned int i, state; + + sandbox_set_enable_memio(true); + + ut_assertok(uclass_get_device_by_name(UCLASS_MUX, "a-mux-controller", + &dev)); + chip = dev_get_uclass_priv(dev); + ut_assertnonnull(chip); + + srand(get_ticks() + rand()); + for (i = 0; i < chip->controllers; i++) { + mux = &chip->mux[i]; + + state = rand() % mux->states; + + snprintf(cmd, BUF_SIZE, "mux select a-mux-controller %x %x", i, + state); + run_command(cmd, 0); + ut_asserteq(!!mux->in_use, true); + ut_asserteq(state, mux->cached_state); + + ut_assertok(mux_control_deselect(mux)); + } + + return 0; +} +DM_TEST(dm_test_cmd_mux_select, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); + +static int dm_test_cmd_mux_deselect(struct unit_test_state *uts) +{ + struct udevice *dev; + struct mux_chip *chip; + struct mux_control *mux; + char cmd[BUF_SIZE]; + unsigned int i, state; + + sandbox_set_enable_memio(true); + + ut_assertok(uclass_get_device_by_name(UCLASS_MUX, "a-mux-controller", + &dev)); + chip = dev_get_uclass_priv(dev); + ut_assertnonnull(chip); + + srand(get_ticks() + rand()); + for (i = 0; i < chip->controllers; i++) { + mux = &chip->mux[i]; + + state = rand() % mux->states; + ut_assertok(mux_control_select(mux, state)); + + snprintf(cmd, BUF_SIZE, "mux deselect a-mux-controller %d", i); + run_command(cmd, 0); + ut_asserteq(!!mux->in_use, false); + } + + return 0; +} +DM_TEST(dm_test_cmd_mux_deselect, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); diff --git a/roms/u-boot/test/dm/mux-emul.c b/roms/u-boot/test/dm/mux-emul.c new file mode 100644 index 000000000..58233edc9 --- /dev/null +++ b/roms/u-boot/test/dm/mux-emul.c @@ -0,0 +1,106 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2020 Texas Instruments Incorporated - http://www.ti.com/ + * Pratyush Yadav <p.yadav@ti.com> + */ +#include <common.h> +#include <dm.h> +#include <mux.h> +#include <mux-internal.h> +#include <dm/test.h> +#include <test/ut.h> +#include <asm/global_data.h> + +struct mux_emul_priv { + u32 state; +}; + +static int mux_emul_set(struct mux_control *mux, int state) +{ + struct mux_emul_priv *priv = dev_get_priv(mux->dev); + + priv->state = state; + return 0; +} + +static int mux_emul_probe(struct udevice *dev) +{ + struct mux_chip *mux_chip = dev_get_uclass_priv(dev); + struct mux_control *mux; + u32 idle_state; + int ret; + + ret = mux_alloc_controllers(dev, 1); + if (ret < 0) + return ret; + + mux = &mux_chip->mux[0]; + + ret = dev_read_u32(dev, "idle-state", &idle_state); + if (ret) + return ret; + + mux->idle_state = idle_state; + mux->states = 0x100000; + + return 0; +} + +static const struct mux_control_ops mux_emul_ops = { + .set = mux_emul_set, +}; + +static const struct udevice_id mux_emul_of_match[] = { + { .compatible = "mux-emul" }, + { /* sentinel */ }, +}; + +U_BOOT_DRIVER(emul_mux) = { + .name = "mux-emul", + .id = UCLASS_MUX, + .of_match = mux_emul_of_match, + .ops = &mux_emul_ops, + .probe = mux_emul_probe, + .priv_auto = sizeof(struct mux_emul_priv), +}; + +static int dm_test_mux_emul_default_state(struct unit_test_state *uts) +{ + struct udevice *dev; + struct mux_control *mux; + struct mux_emul_priv *priv; + + ut_assertok(uclass_get_device_by_name(UCLASS_TEST_FDT, "a-test", + &dev)); + ut_assertok(mux_control_get(dev, "mux4", &mux)); + + priv = dev_get_priv(mux->dev); + + ut_asserteq(0xabcd, priv->state); + + return 0; +} +DM_TEST(dm_test_mux_emul_default_state, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); + +static int dm_test_mux_emul_select_deselect(struct unit_test_state *uts) +{ + struct udevice *dev; + struct mux_control *mux; + struct mux_emul_priv *priv; + + gd->flags &= ~(GD_FLG_SILENT | GD_FLG_RECORD); + ut_assertok(uclass_get_device_by_name(UCLASS_TEST_FDT, "a-test", + &dev)); + ut_assertok(mux_control_get(dev, "mux4", &mux)); + + priv = dev_get_priv(mux->dev); + + ut_assertok(mux_control_select(mux, 0x1234)); + ut_asserteq(priv->state, 0x1234); + + ut_assertok(mux_control_deselect(mux)); + ut_asserteq(priv->state, 0xabcd); + + return 0; +} +DM_TEST(dm_test_mux_emul_select_deselect, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); diff --git a/roms/u-boot/test/dm/mux-mmio.c b/roms/u-boot/test/dm/mux-mmio.c new file mode 100644 index 000000000..fd353d8b1 --- /dev/null +++ b/roms/u-boot/test/dm/mux-mmio.c @@ -0,0 +1,138 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2017-2018 Texas Instruments Incorporated - http://www.ti.com/ + * Jean-Jacques Hiblot <jjhiblot@ti.com> + */ + +#include <common.h> +#include <dm.h> +#include <mux.h> +#include <regmap.h> +#include <syscon.h> +#include <asm/test.h> +#include <dm/test.h> +#include <dm/device-internal.h> +#include <test/ut.h> + +static int dm_test_mux_mmio_select(struct unit_test_state *uts) +{ + struct udevice *dev, *dev_b; + struct regmap *map; + struct mux_control *ctl0_a, *ctl0_b; + struct mux_control *ctl1; + struct mux_control *ctl_err; + u32 val; + int i; + + sandbox_set_enable_memio(true); + + ut_assertok(uclass_get_device_by_name(UCLASS_TEST_FDT, "a-test", + &dev)); + ut_assertok(uclass_get_device_by_name(UCLASS_TEST_FDT, "b-test", + &dev_b)); + map = syscon_regmap_lookup_by_phandle(dev, "mux-syscon"); + ut_assertok_ptr(map); + ut_assert(map); + + ut_assertok(mux_control_get(dev, "mux0", &ctl0_a)); + ut_assertok(mux_control_get(dev, "mux1", &ctl1)); + ut_asserteq(-ERANGE, mux_control_get(dev, "mux3", &ctl_err)); + ut_asserteq(-ENODATA, mux_control_get(dev, "dummy", &ctl_err)); + ut_assertok(mux_control_get(dev_b, "mux0", &ctl0_b)); + + for (i = 0; i < mux_control_states(ctl0_a); i++) { + /* Select a new state and verify the value in the regmap. */ + ut_assertok(mux_control_select(ctl0_a, i)); + ut_assertok(regmap_read(map, 0, &val)); + ut_asserteq(i, (val & 0x30) >> 4); + /* + * Deselect the mux and verify that the value in the regmap + * reflects the idle state (fixed to MUX_IDLE_AS_IS). + */ + ut_assertok(mux_control_deselect(ctl0_a)); + ut_assertok(regmap_read(map, 0, &val)); + ut_asserteq(i, (val & 0x30) >> 4); + } + + for (i = 0; i < mux_control_states(ctl1); i++) { + /* Select a new state and verify the value in the regmap. */ + ut_assertok(mux_control_select(ctl1, i)); + ut_assertok(regmap_read(map, 0xc, &val)); + ut_asserteq(i, (val & 0x1E) >> 1); + /* + * Deselect the mux and verify that the value in the regmap + * reflects the idle state (fixed to 2). + */ + ut_assertok(mux_control_deselect(ctl1)); + ut_assertok(regmap_read(map, 0xc, &val)); + ut_asserteq(2, (val & 0x1E) >> 1); + } + + /* Try unbalanced selection/deselection. */ + ut_assertok(mux_control_select(ctl0_a, 0)); + ut_asserteq(-EBUSY, mux_control_select(ctl0_a, 1)); + ut_asserteq(-EBUSY, mux_control_select(ctl0_a, 0)); + ut_assertok(mux_control_deselect(ctl0_a)); + + /* Try concurrent selection. */ + ut_assertok(mux_control_select(ctl0_a, 0)); + ut_assert(mux_control_select(ctl0_b, 0)); + ut_assertok(mux_control_deselect(ctl0_a)); + ut_assertok(mux_control_select(ctl0_b, 0)); + ut_assert(mux_control_select(ctl0_a, 0)); + ut_assertok(mux_control_deselect(ctl0_b)); + ut_assertok(mux_control_select(ctl0_a, 0)); + ut_assertok(mux_control_deselect(ctl0_a)); + + return 0; +} +DM_TEST(dm_test_mux_mmio_select, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); + +/* Test that managed API for mux work correctly */ +static int dm_test_devm_mux_mmio(struct unit_test_state *uts) +{ + struct udevice *dev, *dev_b; + struct mux_control *ctl0_a, *ctl0_b; + struct mux_control *ctl1; + struct mux_control *ctl_err; + + sandbox_set_enable_memio(true); + + ut_assertok(uclass_get_device_by_name(UCLASS_TEST_FDT, "a-test", + &dev)); + ut_assertok(uclass_get_device_by_name(UCLASS_TEST_FDT, "b-test", + &dev_b)); + + ctl0_a = devm_mux_control_get(dev, "mux0"); + ut_assertok_ptr(ctl0_a); + ut_assert(ctl0_a); + ctl1 = devm_mux_control_get(dev, "mux1"); + ut_assertok_ptr(ctl1); + ut_assert(ctl1); + ctl_err = devm_mux_control_get(dev, "mux3"); + ut_asserteq(-ERANGE, PTR_ERR(ctl_err)); + ctl_err = devm_mux_control_get(dev, "dummy"); + ut_asserteq(-ENODATA, PTR_ERR(ctl_err)); + + ctl0_b = devm_mux_control_get(dev_b, "mux0"); + ut_assertok_ptr(ctl0_b); + ut_assert(ctl0_b); + + /* Try concurrent selection. */ + ut_assertok(mux_control_select(ctl0_a, 0)); + ut_assert(mux_control_select(ctl0_b, 0)); + ut_assertok(mux_control_deselect(ctl0_a)); + ut_assertok(mux_control_select(ctl0_b, 0)); + ut_assert(mux_control_select(ctl0_a, 0)); + ut_assertok(mux_control_deselect(ctl0_b)); + + /* Remove one device and check that the mux is released. */ + ut_assertok(mux_control_select(ctl0_a, 0)); + ut_assert(mux_control_select(ctl0_b, 0)); + device_remove(dev, DM_REMOVE_NORMAL); + ut_assertok(mux_control_select(ctl0_b, 0)); + + device_remove(dev_b, DM_REMOVE_NORMAL); + return 0; +} +DM_TEST(dm_test_devm_mux_mmio, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); diff --git a/roms/u-boot/test/dm/nop.c b/roms/u-boot/test/dm/nop.c new file mode 100644 index 000000000..2cd92c524 --- /dev/null +++ b/roms/u-boot/test/dm/nop.c @@ -0,0 +1,74 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Test for the NOP uclass + * + * (C) Copyright 2019 - Texas Instruments Incorporated - http://www.ti.com/ + * Jean-Jacques Hiblot <jjhiblot@ti.com> + */ + +#include <common.h> +#include <dm.h> +#include <dm/ofnode.h> +#include <dm/lists.h> +#include <dm/device.h> +#include <dm/test.h> +#include <misc.h> +#include <test/test.h> +#include <test/ut.h> + +static int noptest_bind(struct udevice *parent) +{ + ofnode ofnode = dev_read_first_subnode(parent); + + while (ofnode_valid(ofnode)) { + struct udevice *dev; + const char *bind_flag = ofnode_read_string(ofnode, "bind"); + + if (bind_flag && (strcmp(bind_flag, "True") == 0)) + lists_bind_fdt(parent, ofnode, &dev, false); + ofnode = dev_read_next_subnode(ofnode); + } + + return 0; +} + +static const struct udevice_id noptest1_ids[] = { + { + .compatible = "sandbox,nop_sandbox1", + }, + { } +}; + +U_BOOT_DRIVER(noptest_drv1) = { + .name = "noptest1_drv", + .of_match = noptest1_ids, + .id = UCLASS_NOP, + .bind = noptest_bind, +}; + +static const struct udevice_id noptest2_ids[] = { + { + .compatible = "sandbox,nop_sandbox2", + }, + { } +}; + +U_BOOT_DRIVER(noptest_drv2) = { + .name = "noptest2_drv", + .of_match = noptest2_ids, + .id = UCLASS_NOP, +}; + +static int dm_test_nop(struct unit_test_state *uts) +{ + struct udevice *dev; + + ut_assertok(uclass_get_device_by_name(UCLASS_NOP, "nop-test_0", &dev)); + ut_assertok(uclass_get_device_by_name(UCLASS_NOP, "nop-test_1", &dev)); + ut_asserteq(-ENODEV, + uclass_get_device_by_name(UCLASS_NOP, "nop-test_2", &dev)); + + return 0; +} + +DM_TEST(dm_test_nop, UT_TESTF_FLAT_TREE | UT_TESTF_SCAN_FDT); diff --git a/roms/u-boot/test/dm/of_extra.c b/roms/u-boot/test/dm/of_extra.c new file mode 100644 index 000000000..ac2d88689 --- /dev/null +++ b/roms/u-boot/test/dm/of_extra.c @@ -0,0 +1,56 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright 2021 Google LLC + * Written by Simon Glass <sjg@chromium.org> + */ + +#include <common.h> +#include <dm.h> +#include <dm/of_extra.h> +#include <dm/test.h> +#include <test/ut.h> +#include <u-boot/sha256.h> + +static int dm_test_ofnode_read_fmap_entry(struct unit_test_state *uts) +{ + const char hash_expect[] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, + }; + struct fmap_entry entry; + ofnode node; + + node = ofnode_path("/cros-ec/flash/wp-ro"); + ut_assertok(ofnode_read_fmap_entry(node, &entry)); + ut_asserteq(0xf000, entry.offset); + ut_asserteq(0x1000, entry.length); + ut_asserteq(0x884, entry.used); + ut_asserteq(FMAP_COMPRESS_LZ4, entry.compress_algo); + ut_asserteq(0xcf8, entry.unc_length); + ut_asserteq(FMAP_HASH_SHA256, entry.hash_algo); + ut_asserteq(SHA256_SUM_LEN, entry.hash_size); + ut_asserteq_mem(hash_expect, entry.hash, SHA256_SUM_LEN); + + return 0; +} +DM_TEST(dm_test_ofnode_read_fmap_entry, 0); + +static int dm_test_ofnode_phy_is_fixed_link(struct unit_test_state *uts) +{ + ofnode eth_node, phy_node, node; + + eth_node = ofnode_path("/dsa-test/ports/port@0"); + ut_assert(ofnode_phy_is_fixed_link(eth_node, &phy_node)); + node = ofnode_path("/dsa-test/ports/port@0/fixed-link"); + ut_asserteq_mem(&phy_node, &node, sizeof(ofnode)); + + eth_node = ofnode_path("/dsa-test/ports/port@1"); + ut_assert(ofnode_phy_is_fixed_link(eth_node, &phy_node)); + node = eth_node; + ut_asserteq_mem(&phy_node, &node, sizeof(ofnode)); + + return 0; +} +DM_TEST(dm_test_ofnode_phy_is_fixed_link, 0); diff --git a/roms/u-boot/test/dm/of_platdata.c b/roms/u-boot/test/dm/of_platdata.c new file mode 100644 index 000000000..0f89c7a7d --- /dev/null +++ b/roms/u-boot/test/dm/of_platdata.c @@ -0,0 +1,223 @@ +// SPDX-License-Identifier: GPL-2.0+ + +#include <common.h> +#include <dm.h> +#include <dt-structs.h> +#include <dm/test.h> +#include <test/test.h> +#include <test/ut.h> +#include <asm/global_data.h> + +/* Test that we can find a device using of-platdata */ +static int dm_test_of_plat_base(struct unit_test_state *uts) +{ + struct udevice *dev; + + ut_assertok(uclass_first_device_err(UCLASS_SERIAL, &dev)); + ut_asserteq_str("sandbox_serial", dev->name); + + return 0; +} +DM_TEST(dm_test_of_plat_base, UT_TESTF_SCAN_PDATA); + +/* Test that we can read properties from a device */ +static int dm_test_of_plat_props(struct unit_test_state *uts) +{ + struct dtd_sandbox_spl_test *plat; + struct udevice *dev; + int i; + + /* Skip the clock */ + ut_assertok(uclass_first_device_err(UCLASS_MISC, &dev)); + ut_asserteq_str("sandbox_clk_test", dev->name); + + ut_assertok(uclass_next_device_err(&dev)); + plat = dev_get_plat(dev); + ut_assert(plat->boolval); + ut_asserteq(1, plat->intval); + ut_asserteq(4, ARRAY_SIZE(plat->intarray)); + ut_asserteq(2, plat->intarray[0]); + ut_asserteq(3, plat->intarray[1]); + ut_asserteq(4, plat->intarray[2]); + ut_asserteq(0, plat->intarray[3]); + ut_asserteq(5, plat->byteval); + ut_asserteq(3, ARRAY_SIZE(plat->bytearray)); + ut_asserteq(6, plat->bytearray[0]); + ut_asserteq(0, plat->bytearray[1]); + ut_asserteq(0, plat->bytearray[2]); + ut_asserteq(9, ARRAY_SIZE(plat->longbytearray)); + for (i = 0; i < ARRAY_SIZE(plat->longbytearray); i++) + ut_asserteq(9 + i, plat->longbytearray[i]); + ut_asserteq_str("message", plat->stringval); + ut_asserteq(3, ARRAY_SIZE(plat->stringarray)); + ut_asserteq_str("multi-word", plat->stringarray[0]); + ut_asserteq_str("message", plat->stringarray[1]); + ut_asserteq_str("", plat->stringarray[2]); + + ut_assertok(uclass_next_device_err(&dev)); + plat = dev_get_plat(dev); + ut_assert(!plat->boolval); + ut_asserteq(3, plat->intval); + ut_asserteq(5, plat->intarray[0]); + ut_asserteq(0, plat->intarray[1]); + ut_asserteq(0, plat->intarray[2]); + ut_asserteq(0, plat->intarray[3]); + ut_asserteq(8, plat->byteval); + ut_asserteq(3, ARRAY_SIZE(plat->bytearray)); + ut_asserteq(1, plat->bytearray[0]); + ut_asserteq(0x23, plat->bytearray[1]); + ut_asserteq(0x34, plat->bytearray[2]); + for (i = 0; i < ARRAY_SIZE(plat->longbytearray); i++) + ut_asserteq(i < 4 ? 9 + i : 0, plat->longbytearray[i]); + ut_asserteq_str("message2", plat->stringval); + ut_asserteq_str("another", plat->stringarray[0]); + ut_asserteq_str("multi-word", plat->stringarray[1]); + ut_asserteq_str("message", plat->stringarray[2]); + + ut_assertok(uclass_next_device_err(&dev)); + plat = dev_get_plat(dev); + ut_assert(!plat->boolval); + ut_asserteq_str("one", plat->stringarray[0]); + ut_asserteq_str("", plat->stringarray[1]); + ut_asserteq_str("", plat->stringarray[2]); + + ut_assertok(uclass_next_device_err(&dev)); + plat = dev_get_plat(dev); + ut_assert(!plat->boolval); + ut_asserteq_str("spl", plat->stringarray[0]); + + ut_asserteq(-ENODEV, uclass_next_device_err(&dev)); + + return 0; +} +DM_TEST(dm_test_of_plat_props, UT_TESTF_SCAN_PDATA); + +/* + * find_driver_info - recursively find the driver_info for a device + * + * This sets found[idx] to true when it finds the driver_info record for a + * device, where idx is the index in the driver_info linker list. + * + * @uts: Test state + * @parent: Parent to search + * @found: bool array to update + * @return 0 if OK, non-zero on error + */ +static int find_driver_info(struct unit_test_state *uts, struct udevice *parent, + bool found[]) +{ + struct udevice *dev; + + /* If not the root device, find the entry that caused it to be bound */ + if (parent->parent) { + const int n_ents = + ll_entry_count(struct driver_info, driver_info); + int idx = -1; + int i; + + for (i = 0; i < n_ents; i++) { + const struct driver_rt *drt = gd_dm_driver_rt() + i; + + if (drt->dev == parent) { + idx = i; + found[idx] = true; + break; + } + } + + ut_assert(idx != -1); + } + + device_foreach_child(dev, parent) { + int ret; + + ret = find_driver_info(uts, dev, found); + if (ret < 0) + return ret; + } + + return 0; +} + +/* Check that every device is recorded in its driver_info struct */ +static int dm_test_of_plat_dev(struct unit_test_state *uts) +{ + const int n_ents = ll_entry_count(struct driver_info, driver_info); + bool found[n_ents]; + uint i; + + /* Skip this test if there is no platform data */ + if (!CONFIG_IS_ENABLED(OF_PLATDATA_DRIVER_RT)) + return 0; + + /* Record the indexes that are found */ + memset(found, '\0', sizeof(found)); + ut_assertok(find_driver_info(uts, gd->dm_root, found)); + + /* Make sure that the driver entries without devices have no ->dev */ + for (i = 0; i < n_ents; i++) { + const struct driver_rt *drt = gd_dm_driver_rt() + i; + struct udevice *dev; + + if (found[i]) { + /* Make sure we can find it */ + ut_assertnonnull(drt->dev); + ut_assertok(device_get_by_ofplat_idx(i, &dev)); + ut_asserteq_ptr(dev, drt->dev); + } else { + ut_assertnull(drt->dev); + ut_asserteq(-ENOENT, device_get_by_ofplat_idx(i, &dev)); + } + } + + return 0; +} +DM_TEST(dm_test_of_plat_dev, UT_TESTF_SCAN_PDATA); + +/* Test handling of phandles that point to other devices */ +static int dm_test_of_plat_phandle(struct unit_test_state *uts) +{ + struct dtd_sandbox_clk_test *plat; + struct udevice *dev, *clk; + + ut_assertok(uclass_first_device_err(UCLASS_MISC, &dev)); + ut_asserteq_str("sandbox_clk_test", dev->name); + plat = dev_get_plat(dev); + + ut_assertok(device_get_by_ofplat_idx(plat->clocks[0].idx, &clk)); + ut_asserteq_str("sandbox_fixed_clock", clk->name); + + ut_assertok(device_get_by_ofplat_idx(plat->clocks[1].idx, &clk)); + ut_asserteq_str("sandbox_clk", clk->name); + ut_asserteq(1, plat->clocks[1].arg[0]); + + ut_assertok(device_get_by_ofplat_idx(plat->clocks[2].idx, &clk)); + ut_asserteq_str("sandbox_clk", clk->name); + ut_asserteq(0, plat->clocks[2].arg[0]); + + ut_assertok(device_get_by_ofplat_idx(plat->clocks[3].idx, &clk)); + ut_asserteq_str("sandbox_clk", clk->name); + ut_asserteq(3, plat->clocks[3].arg[0]); + + ut_assertok(device_get_by_ofplat_idx(plat->clocks[4].idx, &clk)); + ut_asserteq_str("sandbox_clk", clk->name); + ut_asserteq(2, plat->clocks[4].arg[0]); + + return 0; +} +DM_TEST(dm_test_of_plat_phandle, UT_TESTF_SCAN_PDATA); + +#if CONFIG_IS_ENABLED(OF_PLATDATA_PARENT) +/* Test that device parents are correctly set up */ +static int dm_test_of_plat_parent(struct unit_test_state *uts) +{ + struct udevice *rtc, *i2c; + + ut_assertok(uclass_first_device_err(UCLASS_RTC, &rtc)); + ut_assertok(uclass_first_device_err(UCLASS_I2C, &i2c)); + ut_asserteq_ptr(i2c, dev_get_parent(rtc)); + + return 0; +} +DM_TEST(dm_test_of_plat_parent, UT_TESTF_SCAN_PDATA); +#endif diff --git a/roms/u-boot/test/dm/ofnode.c b/roms/u-boot/test/dm/ofnode.c new file mode 100644 index 000000000..de895773b --- /dev/null +++ b/roms/u-boot/test/dm/ofnode.c @@ -0,0 +1,294 @@ +// SPDX-License-Identifier: GPL-2.0+ + +#include <common.h> +#include <dm.h> +#include <log.h> +#include <dm/of_extra.h> +#include <dm/test.h> +#include <test/test.h> +#include <test/ut.h> + +static int dm_test_ofnode_compatible(struct unit_test_state *uts) +{ + ofnode root_node = ofnode_path("/"); + + ut_assert(ofnode_valid(root_node)); + ut_assert(ofnode_device_is_compatible(root_node, "sandbox")); + + return 0; +} +DM_TEST(dm_test_ofnode_compatible, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); + +static int dm_test_ofnode_get_by_phandle(struct unit_test_state *uts) +{ + /* test invalid phandle */ + ut_assert(!ofnode_valid(ofnode_get_by_phandle(0))); + ut_assert(!ofnode_valid(ofnode_get_by_phandle(-1))); + + /* test first valid phandle */ + ut_assert(ofnode_valid(ofnode_get_by_phandle(1))); + + /* test unknown phandle */ + ut_assert(!ofnode_valid(ofnode_get_by_phandle(0x1000000))); + + return 0; +} +DM_TEST(dm_test_ofnode_get_by_phandle, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); + +static int dm_test_ofnode_by_prop_value(struct unit_test_state *uts) +{ + const char propname[] = "compatible"; + const char propval[] = "denx,u-boot-fdt-test"; + const char *str; + ofnode node = ofnode_null(); + + /* Find first matching node, there should be at least one */ + node = ofnode_by_prop_value(node, propname, propval, sizeof(propval)); + ut_assert(ofnode_valid(node)); + str = ofnode_read_string(node, propname); + ut_assert(str && !strcmp(str, propval)); + + /* Find the rest of the matching nodes */ + while (true) { + node = ofnode_by_prop_value(node, propname, propval, + sizeof(propval)); + if (!ofnode_valid(node)) + break; + str = ofnode_read_string(node, propname); + ut_assert(str && !strcmp(str, propval)); + } + + return 0; +} +DM_TEST(dm_test_ofnode_by_prop_value, UT_TESTF_SCAN_FDT); + +static int dm_test_ofnode_fmap(struct unit_test_state *uts) +{ + struct fmap_entry entry; + ofnode node; + + node = ofnode_path("/cros-ec/flash"); + ut_assert(ofnode_valid(node)); + ut_assertok(ofnode_read_fmap_entry(node, &entry)); + ut_asserteq(0x08000000, entry.offset); + ut_asserteq(0x20000, entry.length); + + return 0; +} +DM_TEST(dm_test_ofnode_fmap, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); + +static int dm_test_ofnode_read(struct unit_test_state *uts) +{ + const u32 *val; + ofnode node; + int size; + + node = ofnode_path("/a-test"); + ut_assert(ofnode_valid(node)); + + val = ofnode_read_prop(node, "int-value", &size); + ut_assertnonnull(val); + ut_asserteq(4, size); + ut_asserteq(1234, fdt32_to_cpu(val[0])); + + val = ofnode_read_prop(node, "missing", &size); + ut_assertnull(val); + ut_asserteq(-FDT_ERR_NOTFOUND, size); + + /* Check it works without a size parameter */ + val = ofnode_read_prop(node, "missing", NULL); + ut_assertnull(val); + + return 0; +} +DM_TEST(dm_test_ofnode_read, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); + +static int dm_test_ofnode_phandle(struct unit_test_state *uts) +{ + struct ofnode_phandle_args args; + ofnode node; + int ret; + const char prop[] = "test-gpios"; + const char cell[] = "#gpio-cells"; + const char prop2[] = "phandle-value"; + + node = ofnode_path("/a-test"); + ut_assert(ofnode_valid(node)); + + /* Test ofnode_count_phandle_with_args with cell name */ + ret = ofnode_count_phandle_with_args(node, "missing", cell, 0); + ut_asserteq(-ENOENT, ret); + ret = ofnode_count_phandle_with_args(node, prop, "#invalid", 0); + ut_asserteq(-EINVAL, ret); + ret = ofnode_count_phandle_with_args(node, prop, cell, 0); + ut_asserteq(5, ret); + + /* Test ofnode_parse_phandle_with_args with cell name */ + ret = ofnode_parse_phandle_with_args(node, "missing", cell, 0, 0, + &args); + ut_asserteq(-ENOENT, ret); + ret = ofnode_parse_phandle_with_args(node, prop, "#invalid", 0, 0, + &args); + ut_asserteq(-EINVAL, ret); + ret = ofnode_parse_phandle_with_args(node, prop, cell, 0, 0, &args); + ut_assertok(ret); + ut_asserteq(1, args.args_count); + ut_asserteq(1, args.args[0]); + ret = ofnode_parse_phandle_with_args(node, prop, cell, 0, 1, &args); + ut_assertok(ret); + ut_asserteq(1, args.args_count); + ut_asserteq(4, args.args[0]); + ret = ofnode_parse_phandle_with_args(node, prop, cell, 0, 2, &args); + ut_assertok(ret); + ut_asserteq(5, args.args_count); + ut_asserteq(5, args.args[0]); + ut_asserteq(1, args.args[4]); + ret = ofnode_parse_phandle_with_args(node, prop, cell, 0, 3, &args); + ut_asserteq(-ENOENT, ret); + ret = ofnode_parse_phandle_with_args(node, prop, cell, 0, 4, &args); + ut_assertok(ret); + ut_asserteq(1, args.args_count); + ut_asserteq(12, args.args[0]); + ret = ofnode_parse_phandle_with_args(node, prop, cell, 0, 5, &args); + ut_asserteq(-ENOENT, ret); + + /* Test ofnode_count_phandle_with_args with cell count */ + ret = ofnode_count_phandle_with_args(node, "missing", NULL, 2); + ut_asserteq(-ENOENT, ret); + ret = ofnode_count_phandle_with_args(node, prop2, NULL, 1); + ut_asserteq(3, ret); + + /* Test ofnode_parse_phandle_with_args with cell count */ + ret = ofnode_parse_phandle_with_args(node, prop2, NULL, 1, 0, &args); + ut_assertok(ret); + ut_asserteq(1, ofnode_valid(args.node)); + ut_asserteq(1, args.args_count); + ut_asserteq(10, args.args[0]); + ret = ofnode_parse_phandle_with_args(node, prop2, NULL, 1, 1, &args); + ut_asserteq(-EINVAL, ret); + ret = ofnode_parse_phandle_with_args(node, prop2, NULL, 1, 2, &args); + ut_assertok(ret); + ut_asserteq(1, ofnode_valid(args.node)); + ut_asserteq(1, args.args_count); + ut_asserteq(30, args.args[0]); + ret = ofnode_parse_phandle_with_args(node, prop2, NULL, 1, 3, &args); + ut_asserteq(-ENOENT, ret); + + return 0; +} +DM_TEST(dm_test_ofnode_phandle, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); + +static int dm_test_ofnode_read_chosen(struct unit_test_state *uts) +{ + const char *str; + const u32 *val; + ofnode node; + int size; + + str = ofnode_read_chosen_string("setting"); + ut_assertnonnull(str); + ut_asserteq_str("sunrise ohoka", str); + ut_asserteq_ptr(NULL, ofnode_read_chosen_string("no-setting")); + + node = ofnode_get_chosen_node("other-node"); + ut_assert(ofnode_valid(node)); + ut_asserteq_str("c-test@5", ofnode_get_name(node)); + + node = ofnode_get_chosen_node("setting"); + ut_assert(!ofnode_valid(node)); + + val = ofnode_read_chosen_prop("int-values", &size); + ut_assertnonnull(val); + ut_asserteq(8, size); + ut_asserteq(0x1937, fdt32_to_cpu(val[0])); + ut_asserteq(72993, fdt32_to_cpu(val[1])); + + return 0; +} +DM_TEST(dm_test_ofnode_read_chosen, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); + +static int dm_test_ofnode_read_aliases(struct unit_test_state *uts) +{ + const void *val; + ofnode node; + int size; + + node = ofnode_get_aliases_node("ethernet3"); + ut_assert(ofnode_valid(node)); + ut_asserteq_str("sbe5", ofnode_get_name(node)); + + node = ofnode_get_aliases_node("unknown"); + ut_assert(!ofnode_valid(node)); + + val = ofnode_read_aliases_prop("spi0", &size); + ut_assertnonnull(val); + ut_asserteq(7, size); + ut_asserteq_str("/spi@0", (const char *)val); + + return 0; +} +DM_TEST(dm_test_ofnode_read_aliases, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); + +static int dm_test_ofnode_get_child_count(struct unit_test_state *uts) +{ + ofnode node, child_node; + u32 val; + + node = ofnode_path("/i-test"); + ut_assert(ofnode_valid(node)); + + val = ofnode_get_child_count(node); + ut_asserteq(3, val); + + child_node = ofnode_first_subnode(node); + ut_assert(ofnode_valid(child_node)); + val = ofnode_get_child_count(child_node); + ut_asserteq(0, val); + + return 0; +} +DM_TEST(dm_test_ofnode_get_child_count, + UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); + +static int dm_test_ofnode_is_enabled(struct unit_test_state *uts) +{ + ofnode root_node = ofnode_path("/"); + ofnode node = ofnode_path("/usb@0"); + + ut_assert(ofnode_is_enabled(root_node)); + ut_assert(!ofnode_is_enabled(node)); + + return 0; +} +DM_TEST(dm_test_ofnode_is_enabled, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); + +static int dm_test_ofnode_get_reg(struct unit_test_state *uts) +{ + ofnode node; + fdt_addr_t addr; + fdt_size_t size; + + node = ofnode_path("/translation-test@8000"); + ut_assert(ofnode_valid(node)); + addr = ofnode_get_addr(node); + size = ofnode_get_size(node); + ut_asserteq(0x8000, addr); + ut_asserteq(0x4000, size); + + node = ofnode_path("/translation-test@8000/dev@1,100"); + ut_assert(ofnode_valid(node)); + addr = ofnode_get_addr(node); + size = ofnode_get_size(node); + ut_asserteq(0x9000, addr); + ut_asserteq(0x1000, size); + + node = ofnode_path("/emul-mux-controller"); + ut_assert(ofnode_valid(node)); + addr = ofnode_get_addr(node); + size = ofnode_get_size(node); + ut_asserteq(FDT_ADDR_T_NONE, addr); + ut_asserteq(FDT_SIZE_T_NONE, size); + + return 0; +} +DM_TEST(dm_test_ofnode_get_reg, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); diff --git a/roms/u-boot/test/dm/ofread.c b/roms/u-boot/test/dm/ofread.c new file mode 100644 index 000000000..8c7dd8251 --- /dev/null +++ b/roms/u-boot/test/dm/ofread.c @@ -0,0 +1,50 @@ +// SPDX-License-Identifier: GPL-2.0+ + +#include <common.h> +#include <dm.h> +#include <dm/test.h> +#include <test/ut.h> + +static int dm_test_ofnode_get_property_by_prop(struct unit_test_state *uts) +{ + ofnode node; + struct ofprop prop; + const void *value; + const char *propname; + int res, len, count = 0; + + node = ofnode_path("/cros-ec/flash"); + for (res = ofnode_get_first_property(node, &prop); + !res; + res = ofnode_get_next_property(&prop)) { + value = ofnode_get_property_by_prop(&prop, &propname, &len); + ut_assertnonnull(value); + switch (count) { + case 0: + ut_asserteq_str("image-pos", propname); + ut_asserteq(4, len); + break; + case 1: + ut_asserteq_str("size", propname); + ut_asserteq(4, len); + break; + case 2: + ut_asserteq_str("erase-value", propname); + ut_asserteq(4, len); + break; + case 3: + /* only for plat */ + ut_asserteq_str("name", propname); + ut_asserteq(6, len); + ut_asserteq_str("flash", value); + break; + default: + break; + } + count++; + } + + return 0; +} +DM_TEST(dm_test_ofnode_get_property_by_prop, + UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); diff --git a/roms/u-boot/test/dm/osd.c b/roms/u-boot/test/dm/osd.c new file mode 100644 index 000000000..6279b391c --- /dev/null +++ b/roms/u-boot/test/dm/osd.c @@ -0,0 +1,219 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * (C) Copyright 2018 + * Mario Six, Guntermann & Drunck GmbH, mario.six@gdsys.cc + */ + +#include <common.h> +#include <display_options.h> +#include <dm.h> +#include <video_osd.h> +#include <asm/test.h> +#include <dm/test.h> +#include <test/test.h> +#include <test/ut.h> + +#include "../../drivers/video/sandbox_osd.h" + +const uint memsize = 2 * 10 * 10; + +static void split(u8 *mem, uint size, u8 *text, u8 *colors) +{ + int i; + u16 *p = (u16 *)mem; + + for (i = 0; i < size; i++) { + colors[i] = p[i] % 0x100; + text[i] = p[i] / 0x100; + } +} + +static void print_mem(u8 *mem, uint width, uint height) +{ + const uint memsize = 2 * 10 * 10; + u8 colors[memsize / 2]; + u8 text[memsize / 2]; + int i; + + split(mem, memsize / 2, text, colors); + + for (i = 0; i < width * height; i++) { + printf("%c", text[i]); + if (i > 0 && ((i + 1) % width) == 0) + printf("\n"); + } + + printf("\n"); + + for (i = 0; i < width * height; i++) { + printf("%c", colors[i]); + if (i > 0 && ((i + 1) % width) == 0) + printf("\n"); + } +} + +static int dm_test_osd_basics(struct unit_test_state *uts) +{ + struct udevice *dev; + u8 mem[memsize + 1]; + u8 colors[memsize / 2]; + u8 text[memsize / 2]; + struct video_osd_info info; + + ut_assertok(uclass_first_device_err(UCLASS_VIDEO_OSD, &dev)); + + video_osd_get_info(dev, &info); + + ut_asserteq(10, info.width); + ut_asserteq(10, info.height); + ut_asserteq(1, info.major_version); + ut_asserteq(0, info.minor_version); + + ut_assertok(sandbox_osd_get_mem(dev, mem, memsize)); + split(mem, memsize / 2, text, colors); + + ut_asserteq_mem(text, + " " + " " + " " + " " + " " + " " + " " + " " + " " + " ", memsize / 2); + + ut_asserteq_mem(colors, + "kkkkkkkkkk" + "kkkkkkkkkk" + "kkkkkkkkkk" + "kkkkkkkkkk" + "kkkkkkkkkk" + "kkkkkkkkkk" + "kkkkkkkkkk" + "kkkkkkkkkk" + "kkkkkkkkkk" + "kkkkkkkkkk", memsize / 2); + + print_mem(mem, 10, 10); + + ut_assertok(video_osd_print(dev, 1, 1, COLOR_RED, "Blah")); + + ut_assertok(sandbox_osd_get_mem(dev, mem, memsize)); + split(mem, memsize / 2, text, colors); + + ut_asserteq_mem(text, + " " + " Blah " + " " + " " + " " + " " + " " + " " + " " + " ", memsize / 2); + + ut_asserteq_mem(colors, + "kkkkkkkkkk" + "krrrrkkkkk" + "kkkkkkkkkk" + "kkkkkkkkkk" + "kkkkkkkkkk" + "kkkkkkkkkk" + "kkkkkkkkkk" + "kkkkkkkkkk" + "kkkkkkkkkk" + "kkkkkkkkkk", memsize / 2); + + print_mem(mem, 10, 10); + + return 0; +} + +DM_TEST(dm_test_osd_basics, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); + +static int dm_test_osd_extended(struct unit_test_state *uts) +{ + struct udevice *dev; + u8 mem[memsize + 1]; + u8 colors[memsize / 2]; + u8 text[memsize / 2]; + struct video_osd_info info; + u16 val; + + ut_assertok(uclass_first_device_err(UCLASS_VIDEO_OSD, &dev)); + + ut_assertok(video_osd_set_size(dev, 20, 5)); + + video_osd_get_info(dev, &info); + + ut_asserteq(20, info.width); + ut_asserteq(5, info.height); + ut_asserteq(1, info.major_version); + ut_asserteq(0, info.minor_version); + + ut_assertok(sandbox_osd_get_mem(dev, mem, memsize)); + split(mem, memsize / 2, text, colors); + + ut_asserteq_mem(text, + " " + " " + " " + " " + " ", memsize / 2); + + ut_asserteq_mem(colors, + "kkkkkkkkkkkkkkkkkkkk" + "kkkkkkkkkkkkkkkkkkkk" + "kkkkkkkkkkkkkkkkkkkk" + "kkkkkkkkkkkkkkkkkkkk" + "kkkkkkkkkkkkkkkkkkkk", memsize / 2); + + print_mem(mem, 20, 5); + + /* Draw green border */ + val = '-' * 0x100 + 'g'; + ut_assertok(video_osd_set_mem(dev, 1, 0, (u8 *)&val, 2, 18)); + ut_assertok(video_osd_set_mem(dev, 1, 4, (u8 *)&val, 2, 18)); + ut_assertok(video_osd_print(dev, 0, 1, COLOR_GREEN, "|")); + ut_assertok(video_osd_print(dev, 0, 2, COLOR_GREEN, "|")); + ut_assertok(video_osd_print(dev, 0, 3, COLOR_GREEN, "|")); + ut_assertok(video_osd_print(dev, 19, 1, COLOR_GREEN, "|")); + ut_assertok(video_osd_print(dev, 19, 2, COLOR_GREEN, "|")); + ut_assertok(video_osd_print(dev, 19, 3, COLOR_GREEN, "|")); + ut_assertok(video_osd_print(dev, 0, 0, COLOR_GREEN, "+")); + ut_assertok(video_osd_print(dev, 19, 0, COLOR_GREEN, "+")); + ut_assertok(video_osd_print(dev, 19, 4, COLOR_GREEN, "+")); + ut_assertok(video_osd_print(dev, 0, 4, COLOR_GREEN, "+")); + + /* Add menu caption and entries */ + ut_assertok(video_osd_print(dev, 5, 0, COLOR_GREEN, " OSD menu ")); + ut_assertok(video_osd_print(dev, 2, 1, COLOR_BLUE, " * Entry 1")); + ut_assertok(video_osd_print(dev, 2, 2, COLOR_BLUE, "(*) Entry 2")); + ut_assertok(video_osd_print(dev, 2, 3, COLOR_BLUE, " * Entry 3")); + + ut_assertok(sandbox_osd_get_mem(dev, mem, memsize)); + split(mem, memsize / 2, text, colors); + + print_mem(mem, 20, 5); + + ut_asserteq_mem(text, + "+---- OSD menu ----+" + "| * Entry 1 |" + "| (*) Entry 2 |" + "| * Entry 3 |" + "+------------------+", memsize / 2); + + ut_asserteq_mem(colors, + "gggggggggggggggggggg" + "gkbbbbbbbbbbbkkkkkkg" + "gkbbbbbbbbbbbkkkkkkg" + "gkbbbbbbbbbbbkkkkkkg" + "gggggggggggggggggggg", memsize / 2); + + return 0; +} + +DM_TEST(dm_test_osd_extended, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); diff --git a/roms/u-boot/test/dm/p2sb.c b/roms/u-boot/test/dm/p2sb.c new file mode 100644 index 000000000..df2470914 --- /dev/null +++ b/roms/u-boot/test/dm/p2sb.c @@ -0,0 +1,28 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Test for Primary-to-Sideband bus (P2SB) + * + * Copyright 2019 Google LLC + */ + +#include <common.h> +#include <dm.h> +#include <p2sb.h> +#include <asm/test.h> +#include <dm/test.h> +#include <test/ut.h> + +/* Base test of the PMC uclass */ +static int dm_test_p2sb_base(struct unit_test_state *uts) +{ + struct udevice *dev; + + sandbox_set_enable_memio(true); + ut_assertok(uclass_get_device_by_name(UCLASS_AXI, "adder", &dev)); + ut_asserteq(0x03000004, pcr_read32(dev, 4)); + ut_asserteq(0x300, pcr_read16(dev, 6)); + ut_asserteq(4, pcr_read8(dev, 4)); + + return 0; +} +DM_TEST(dm_test_p2sb_base, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); diff --git a/roms/u-boot/test/dm/panel.c b/roms/u-boot/test/dm/panel.c new file mode 100644 index 000000000..49f5ac716 --- /dev/null +++ b/roms/u-boot/test/dm/panel.c @@ -0,0 +1,80 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Test for panel uclass + * + * Copyright (c) 2018 Google, Inc + * Written by Simon Glass <sjg@chromium.org> + */ + +#include <common.h> +#include <backlight.h> +#include <dm.h> +#include <panel.h> +#include <video.h> +#include <asm/gpio.h> +#include <asm/test.h> +#include <dm/test.h> +#include <power/regulator.h> +#include <test/test.h> +#include <test/ut.h> + +/* Basic test of the panel uclass */ +static int dm_test_panel(struct unit_test_state *uts) +{ + struct udevice *dev, *pwm, *gpio, *reg; + uint period_ns; + uint duty_ns; + bool enable; + bool polarity; + + ut_assertok(uclass_first_device_err(UCLASS_PANEL, &dev)); + ut_assertok(uclass_first_device_err(UCLASS_PWM, &pwm)); + ut_assertok(uclass_get_device(UCLASS_GPIO, 1, &gpio)); + ut_assertok(regulator_get_by_platname("VDD_EMMC_1.8V", ®)); + ut_assertok(sandbox_pwm_get_config(pwm, 0, &period_ns, &duty_ns, + &enable, &polarity)); + ut_asserteq(false, enable); + ut_asserteq(false, regulator_get_enable(reg)); + + ut_assertok(panel_enable_backlight(dev)); + ut_assertok(sandbox_pwm_get_config(pwm, 0, &period_ns, &duty_ns, + &enable, &polarity)); + ut_asserteq(1000, period_ns); + ut_asserteq(170 * 1000 / 255, duty_ns); + ut_asserteq(true, enable); + ut_asserteq(false, polarity); + ut_asserteq(1, sandbox_gpio_get_value(gpio, 1)); + ut_asserteq(true, regulator_get_enable(reg)); + + ut_assertok(panel_set_backlight(dev, 40)); + ut_assertok(sandbox_pwm_get_config(pwm, 0, &period_ns, &duty_ns, + &enable, &polarity)); + ut_asserteq(64 * 1000 / 255, duty_ns); + + ut_assertok(panel_set_backlight(dev, BACKLIGHT_MAX)); + ut_assertok(sandbox_pwm_get_config(pwm, 0, &period_ns, &duty_ns, + &enable, &polarity)); + ut_asserteq(255 * 1000 / 255, duty_ns); + + ut_assertok(panel_set_backlight(dev, BACKLIGHT_MIN)); + ut_assertok(sandbox_pwm_get_config(pwm, 0, &period_ns, &duty_ns, + &enable, &polarity)); + ut_asserteq(0 * 1000 / 255, duty_ns); + ut_asserteq(1, sandbox_gpio_get_value(gpio, 1)); + + ut_assertok(panel_set_backlight(dev, BACKLIGHT_DEFAULT)); + ut_assertok(sandbox_pwm_get_config(pwm, 0, &period_ns, &duty_ns, + &enable, &polarity)); + ut_asserteq(true, enable); + ut_asserteq(170 * 1000 / 255, duty_ns); + + ut_assertok(panel_set_backlight(dev, BACKLIGHT_OFF)); + ut_assertok(sandbox_pwm_get_config(pwm, 0, &period_ns, &duty_ns, + &enable, &polarity)); + ut_asserteq(0 * 1000 / 255, duty_ns); + ut_asserteq(0, sandbox_gpio_get_value(gpio, 1)); + ut_asserteq(false, regulator_get_enable(reg)); + + return 0; +} +DM_TEST(dm_test_panel, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); diff --git a/roms/u-boot/test/dm/part.c b/roms/u-boot/test/dm/part.c new file mode 100644 index 000000000..78dd8472c --- /dev/null +++ b/roms/u-boot/test/dm/part.c @@ -0,0 +1,99 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2020 Sean Anderson <sean.anderson@seco.com> + */ + +#include <common.h> +#include <dm.h> +#include <mmc.h> +#include <part.h> +#include <part_efi.h> +#include <dm/test.h> +#include <test/ut.h> + +static inline int do_test(struct unit_test_state *uts, int expected, + const char *part_str, bool whole) +{ + struct blk_desc *mmc_dev_desc; + struct disk_partition part_info; + + ut_asserteq(expected, + part_get_info_by_dev_and_name_or_num("mmc", part_str, + &mmc_dev_desc, + &part_info, whole)); + return 0; +} + +static int dm_test_part(struct unit_test_state *uts) +{ + char *oldbootdevice; + char str_disk_guid[UUID_STR_LEN + 1]; + int ret; + struct blk_desc *mmc_dev_desc; + struct disk_partition parts[2] = { + { + .start = 48, /* GPT data takes up the first 34 blocks or so */ + .size = 1, + .name = "test1", + }, + { + .start = 49, + .size = 1, + .name = "test2", + }, + }; + + ut_asserteq(1, blk_get_device_by_str("mmc", "1", &mmc_dev_desc)); + if (CONFIG_IS_ENABLED(RANDOM_UUID)) { + gen_rand_uuid_str(parts[0].uuid, UUID_STR_FORMAT_STD); + gen_rand_uuid_str(parts[1].uuid, UUID_STR_FORMAT_STD); + gen_rand_uuid_str(str_disk_guid, UUID_STR_FORMAT_STD); + } + ut_assertok(gpt_restore(mmc_dev_desc, str_disk_guid, parts, + ARRAY_SIZE(parts))); + + oldbootdevice = env_get("bootdevice"); + +#define test(expected, part_str, whole) do { \ + ret = do_test(uts, expected, part_str, whole); \ + if (ret) \ + goto out; \ +} while (0) + + env_set("bootdevice", NULL); + test(-ENODEV, NULL, true); + test(-ENODEV, "", true); + env_set("bootdevice", "0"); + test(0, NULL, true); + test(0, "", true); + env_set("bootdevice", "1"); + test(1, NULL, false); + test(1, "", false); + test(1, "-", false); + env_set("bootdevice", ""); + test(-EPROTONOSUPPORT, "0", false); + test(0, "0", true); + test(0, ":0", true); + test(0, ".0", true); + test(0, ".0:0", true); + test(-EINVAL, "#test1", true); + test(1, "1", false); + test(1, "1", true); + test(-ENOENT, "1:0", false); + test(0, "1:0", true); + test(1, "1:1", false); + test(2, "1:2", false); + test(1, "1.0", false); + test(0, "1.0:0", true); + test(1, "1.0:1", false); + test(2, "1.0:2", false); + test(-EINVAL, "1#bogus", false); + test(1, "1#test1", false); + test(2, "1#test2", false); + ret = 0; + +out: + env_set("bootdevice", oldbootdevice); + return ret; +} +DM_TEST(dm_test_part, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); diff --git a/roms/u-boot/test/dm/pch.c b/roms/u-boot/test/dm/pch.c new file mode 100644 index 000000000..53f7bbf18 --- /dev/null +++ b/roms/u-boot/test/dm/pch.c @@ -0,0 +1,56 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright 2018 Google LLC + */ + +#include <common.h> +#include <dm.h> +#include <pch.h> +#include <asm/test.h> +#include <dm/test.h> +#include <test/test.h> +#include <test/ut.h> + +/* Test that sandbox PCH works correctly */ +static int dm_test_pch_base(struct unit_test_state *uts) +{ + struct udevice *dev; + u32 gbase, iobase; + ulong sbase; + + ut_assertok(uclass_first_device_err(UCLASS_PCH, &dev)); + ut_assertok(pch_get_spi_base(dev, &sbase)); + ut_asserteq(0x10, sbase); + + ut_asserteq(0, sandbox_get_pch_spi_protect(dev)); + ut_assertok(pch_set_spi_protect(dev, true)); + ut_asserteq(1, sandbox_get_pch_spi_protect(dev)); + + ut_assertok(pch_get_gpio_base(dev, &gbase)); + ut_asserteq(0x20, gbase); + + ut_assertok(pch_get_io_base(dev, &iobase)); + ut_asserteq(0x30, iobase); + + return 0; +} +DM_TEST(dm_test_pch_base, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); + +/* Test sandbox PCH ioctl */ +static int dm_test_pch_ioctl(struct unit_test_state *uts) +{ + struct udevice *dev; + char data; + + ut_assertok(uclass_first_device_err(UCLASS_PCH, &dev)); + + ut_asserteq(-ENOSYS, pch_ioctl(dev, PCH_REQ_TEST1, NULL, 0)); + + ut_asserteq('a', pch_ioctl(dev, PCH_REQ_TEST2, "a", 1)); + + ut_asserteq(1, pch_ioctl(dev, PCH_REQ_TEST3, &data, 1)); + ut_asserteq('x', data); + + return 0; +} +DM_TEST(dm_test_pch_ioctl, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); diff --git a/roms/u-boot/test/dm/pci.c b/roms/u-boot/test/dm/pci.c new file mode 100644 index 000000000..fa2e4a855 --- /dev/null +++ b/roms/u-boot/test/dm/pci.c @@ -0,0 +1,378 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2015 Google, Inc + */ + +#include <common.h> +#include <dm.h> +#include <asm/io.h> +#include <asm/test.h> +#include <dm/test.h> +#include <test/test.h> +#include <test/ut.h> + +/* Test that sandbox PCI works correctly */ +static int dm_test_pci_base(struct unit_test_state *uts) +{ + struct udevice *bus; + + ut_assertok(uclass_get_device(UCLASS_PCI, 0, &bus)); + + return 0; +} +DM_TEST(dm_test_pci_base, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); + +/* Test that sandbox PCI bus numbering and device works correctly */ +static int dm_test_pci_busdev(struct unit_test_state *uts) +{ + struct udevice *bus; + struct udevice *swap; + u16 vendor, device; + + /* Test bus#0 and its devices */ + ut_assertok(uclass_get_device_by_seq(UCLASS_PCI, 0, &bus)); + + ut_assertok(dm_pci_bus_find_bdf(PCI_BDF(0, 0x00, 0), &swap)); + vendor = 0; + ut_assertok(dm_pci_read_config16(swap, PCI_VENDOR_ID, &vendor)); + ut_asserteq(SANDBOX_PCI_VENDOR_ID, vendor); + ut_assertok(dm_pci_bus_find_bdf(PCI_BDF(0, 0x1f, 0), &swap)); + device = 0; + ut_assertok(dm_pci_read_config16(swap, PCI_DEVICE_ID, &device)); + ut_asserteq(SANDBOX_PCI_SWAP_CASE_EMUL_ID, device); + + /* Test bus#1 and its devices */ + ut_assertok(uclass_get_device_by_seq(UCLASS_PCI, 1, &bus)); + + ut_assertok(dm_pci_bus_find_bdf(PCI_BDF(1, 0x08, 0), &swap)); + vendor = 0; + ut_assertok(dm_pci_read_config16(swap, PCI_VENDOR_ID, &vendor)); + ut_asserteq(SANDBOX_PCI_VENDOR_ID, vendor); + ut_assertok(dm_pci_bus_find_bdf(PCI_BDF(1, 0x0c, 0), &swap)); + device = 0; + ut_assertok(dm_pci_read_config16(swap, PCI_DEVICE_ID, &device)); + ut_asserteq(SANDBOX_PCI_SWAP_CASE_EMUL_ID, device); + + return 0; +} +DM_TEST(dm_test_pci_busdev, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); + +/* Test that we can use the swapcase device correctly */ +static int dm_test_pci_swapcase(struct unit_test_state *uts) +{ + struct udevice *swap; + ulong io_addr, mem_addr; + char *ptr; + + /* Check that asking for the device 0 automatically fires up PCI */ + ut_assertok(dm_pci_bus_find_bdf(PCI_BDF(0, 0x00, 0), &swap)); + + /* First test I/O */ + io_addr = dm_pci_read_bar32(swap, 0); + outb(2, io_addr); + ut_asserteq(2, inb(io_addr)); + + /* + * Now test memory mapping - note we must unmap and remap to cause + * the swapcase emulation to see our data and response. + */ + mem_addr = dm_pci_read_bar32(swap, 1); + ptr = map_sysmem(mem_addr, 20); + strcpy(ptr, "This is a TesT"); + unmap_sysmem(ptr); + + ptr = map_sysmem(mem_addr, 20); + ut_asserteq_str("tHIS IS A tESt", ptr); + unmap_sysmem(ptr); + + /* Check that asking for the device 1 automatically fires up PCI */ + ut_assertok(dm_pci_bus_find_bdf(PCI_BDF(0, 0x1f, 0), &swap)); + + /* First test I/O */ + io_addr = dm_pci_read_bar32(swap, 0); + outb(2, io_addr); + ut_asserteq(2, inb(io_addr)); + + /* + * Now test memory mapping - note we must unmap and remap to cause + * the swapcase emulation to see our data and response. + */ + mem_addr = dm_pci_read_bar32(swap, 1); + ptr = map_sysmem(mem_addr, 20); + strcpy(ptr, "This is a TesT"); + unmap_sysmem(ptr); + + ptr = map_sysmem(mem_addr, 20); + ut_asserteq_str("tHIS IS A tESt", ptr); + unmap_sysmem(ptr); + + return 0; +} +DM_TEST(dm_test_pci_swapcase, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); + +/* Test that we can dynamically bind the device driver correctly */ +static int dm_test_pci_drvdata(struct unit_test_state *uts) +{ + struct udevice *bus, *swap; + + /* Check that asking for the device automatically fires up PCI */ + ut_assertok(uclass_get_device_by_seq(UCLASS_PCI, 1, &bus)); + + ut_assertok(dm_pci_bus_find_bdf(PCI_BDF(1, 0x08, 0), &swap)); + ut_asserteq(SWAP_CASE_DRV_DATA, swap->driver_data); + ut_assertok(dev_has_ofnode(swap)); + ut_assertok(dm_pci_bus_find_bdf(PCI_BDF(1, 0x0c, 0), &swap)); + ut_asserteq(SWAP_CASE_DRV_DATA, swap->driver_data); + ut_assertok(dev_has_ofnode(swap)); + ut_assertok(dm_pci_bus_find_bdf(PCI_BDF(1, 0x10, 0), &swap)); + ut_asserteq(SWAP_CASE_DRV_DATA, swap->driver_data); + ut_assertok(!dev_has_ofnode(swap)); + + return 0; +} +DM_TEST(dm_test_pci_drvdata, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); + +/* Test that devices on PCI bus#2 can be accessed correctly */ +static int dm_test_pci_mixed(struct unit_test_state *uts) +{ + /* PCI bus#2 has both statically and dynamic declared devices */ + struct udevice *bus, *swap; + u16 vendor, device; + ulong io_addr, mem_addr; + char *ptr; + + ut_assertok(uclass_get_device_by_seq(UCLASS_PCI, 2, &bus)); + + /* Test the dynamic device */ + ut_assertok(dm_pci_bus_find_bdf(PCI_BDF(2, 0x08, 0), &swap)); + vendor = 0; + ut_assertok(dm_pci_read_config16(swap, PCI_VENDOR_ID, &vendor)); + ut_asserteq(SANDBOX_PCI_VENDOR_ID, vendor); + + /* First test I/O */ + io_addr = dm_pci_read_bar32(swap, 0); + outb(2, io_addr); + ut_asserteq(2, inb(io_addr)); + + /* + * Now test memory mapping - note we must unmap and remap to cause + * the swapcase emulation to see our data and response. + */ + mem_addr = dm_pci_read_bar32(swap, 1); + ptr = map_sysmem(mem_addr, 30); + strcpy(ptr, "This is a TesT oN dYNAMIc"); + unmap_sysmem(ptr); + + ptr = map_sysmem(mem_addr, 30); + ut_asserteq_str("tHIS IS A tESt On DynamiC", ptr); + unmap_sysmem(ptr); + + /* Test the static device */ + ut_assertok(dm_pci_bus_find_bdf(PCI_BDF(2, 0x1f, 0), &swap)); + device = 0; + ut_assertok(dm_pci_read_config16(swap, PCI_DEVICE_ID, &device)); + ut_asserteq(SANDBOX_PCI_SWAP_CASE_EMUL_ID, device); + + /* First test I/O */ + io_addr = dm_pci_read_bar32(swap, 0); + outb(2, io_addr); + ut_asserteq(2, inb(io_addr)); + + /* + * Now test memory mapping - note we must unmap and remap to cause + * the swapcase emulation to see our data and response. + */ + mem_addr = dm_pci_read_bar32(swap, 1); + ptr = map_sysmem(mem_addr, 30); + strcpy(ptr, "This is a TesT oN sTATIc"); + unmap_sysmem(ptr); + + ptr = map_sysmem(mem_addr, 30); + ut_asserteq_str("tHIS IS A tESt On StatiC", ptr); + unmap_sysmem(ptr); + + return 0; +} +DM_TEST(dm_test_pci_mixed, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); + +/* Test looking up PCI capability and extended capability */ +static int dm_test_pci_cap(struct unit_test_state *uts) +{ + struct udevice *bus, *swap; + int cap; + + ut_assertok(uclass_get_device_by_seq(UCLASS_PCI, 0, &bus)); + ut_assertok(dm_pci_bus_find_bdf(PCI_BDF(0, 0x1f, 0), &swap)); + + /* look up PCI_CAP_ID_EXP */ + cap = dm_pci_find_capability(swap, PCI_CAP_ID_EXP); + ut_asserteq(PCI_CAP_ID_EXP_OFFSET, cap); + + /* look up PCI_CAP_ID_PCIX */ + cap = dm_pci_find_capability(swap, PCI_CAP_ID_PCIX); + ut_asserteq(0, cap); + + /* look up PCI_CAP_ID_MSIX starting from PCI_CAP_ID_PM_OFFSET */ + cap = dm_pci_find_next_capability(swap, PCI_CAP_ID_PM_OFFSET, + PCI_CAP_ID_MSIX); + ut_asserteq(PCI_CAP_ID_MSIX_OFFSET, cap); + + /* look up PCI_CAP_ID_VNDR starting from PCI_CAP_ID_EXP_OFFSET */ + cap = dm_pci_find_next_capability(swap, PCI_CAP_ID_EXP_OFFSET, + PCI_CAP_ID_VNDR); + ut_asserteq(0, cap); + + ut_assertok(uclass_get_device_by_seq(UCLASS_PCI, 1, &bus)); + ut_assertok(dm_pci_bus_find_bdf(PCI_BDF(1, 0x08, 0), &swap)); + + /* look up PCI_EXT_CAP_ID_DSN */ + cap = dm_pci_find_ext_capability(swap, PCI_EXT_CAP_ID_DSN); + ut_asserteq(PCI_EXT_CAP_ID_DSN_OFFSET, cap); + + /* look up PCI_EXT_CAP_ID_SRIOV */ + cap = dm_pci_find_ext_capability(swap, PCI_EXT_CAP_ID_SRIOV); + ut_asserteq(0, cap); + + /* look up PCI_EXT_CAP_ID_DSN starting from PCI_EXT_CAP_ID_ERR_OFFSET */ + cap = dm_pci_find_next_ext_capability(swap, PCI_EXT_CAP_ID_ERR_OFFSET, + PCI_EXT_CAP_ID_DSN); + ut_asserteq(PCI_EXT_CAP_ID_DSN_OFFSET, cap); + + /* look up PCI_EXT_CAP_ID_RCRB starting from PCI_EXT_CAP_ID_VC_OFFSET */ + cap = dm_pci_find_next_ext_capability(swap, PCI_EXT_CAP_ID_VC_OFFSET, + PCI_EXT_CAP_ID_RCRB); + ut_asserteq(0, cap); + + return 0; +} +DM_TEST(dm_test_pci_cap, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); + +/* Test looking up BARs in EA capability structure */ +static int dm_test_pci_ea(struct unit_test_state *uts) +{ + struct udevice *bus, *swap; + void *bar; + int cap; + + /* + * use emulated device mapping function, we're not using real physical + * addresses in this test + */ + sandbox_set_enable_pci_map(true); + + ut_assertok(uclass_get_device_by_seq(UCLASS_PCI, 0, &bus)); + ut_assertok(dm_pci_bus_find_bdf(PCI_BDF(0, 0x01, 0), &swap)); + + /* look up PCI_CAP_ID_EA */ + cap = dm_pci_find_capability(swap, PCI_CAP_ID_EA); + ut_asserteq(PCI_CAP_ID_EA_OFFSET, cap); + + /* test swap case in BAR 1 */ + bar = dm_pci_map_bar(swap, PCI_BASE_ADDRESS_0, 0); + ut_assertnonnull(bar); + *(int *)bar = 2; /* swap upper/lower */ + + bar = dm_pci_map_bar(swap, PCI_BASE_ADDRESS_1, 0); + ut_assertnonnull(bar); + strcpy(bar, "ea TEST"); + unmap_sysmem(bar); + bar = dm_pci_map_bar(swap, PCI_BASE_ADDRESS_1, 0); + ut_assertnonnull(bar); + ut_asserteq_str("EA test", bar); + + /* test magic values in BARs2, 4; BAR 3 is n/a */ + bar = dm_pci_map_bar(swap, PCI_BASE_ADDRESS_2, 0); + ut_assertnonnull(bar); + ut_asserteq(PCI_EA_BAR2_MAGIC, *(u32 *)bar); + + bar = dm_pci_map_bar(swap, PCI_BASE_ADDRESS_3, 0); + ut_assertnull(bar); + + bar = dm_pci_map_bar(swap, PCI_BASE_ADDRESS_4, 0); + ut_assertnonnull(bar); + ut_asserteq(PCI_EA_BAR4_MAGIC, *(u32 *)bar); + + return 0; +} +DM_TEST(dm_test_pci_ea, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); + +/* Test the dev_read_addr_pci() function */ +static int dm_test_pci_addr_flat(struct unit_test_state *uts) +{ + struct udevice *swap1f, *swap1; + ulong io_addr, mem_addr; + + ut_assertok(dm_pci_bus_find_bdf(PCI_BDF(0, 0x1f, 0), &swap1f)); + io_addr = dm_pci_read_bar32(swap1f, 0); + ut_asserteq(io_addr, dev_read_addr_pci(swap1f)); + + /* + * This device has both I/O and MEM spaces but the MEM space appears + * first + */ + ut_assertok(dm_pci_bus_find_bdf(PCI_BDF(0, 0x1, 0), &swap1)); + mem_addr = dm_pci_read_bar32(swap1, 1); + ut_asserteq(mem_addr, dev_read_addr_pci(swap1)); + + return 0; +} +DM_TEST(dm_test_pci_addr_flat, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT | + UT_TESTF_FLAT_TREE); + +/* + * Test the dev_read_addr_pci() function with livetree. That function is + * not currently fully implemented, in that it fails to return the BAR address. + * Once that is implemented this test can be removed and dm_test_pci_addr_flat() + * can be used for both flattree and livetree by removing the UT_TESTF_FLAT_TREE + * flag above. + */ +static int dm_test_pci_addr_live(struct unit_test_state *uts) +{ + struct udevice *swap1f, *swap1; + + ut_assertok(dm_pci_bus_find_bdf(PCI_BDF(0, 0x1f, 0), &swap1f)); + ut_asserteq(FDT_ADDR_T_NONE, dev_read_addr_pci(swap1f)); + + ut_assertok(dm_pci_bus_find_bdf(PCI_BDF(0, 0x1, 0), &swap1)); + ut_asserteq(FDT_ADDR_T_NONE, dev_read_addr_pci(swap1)); + + return 0; +} +DM_TEST(dm_test_pci_addr_live, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT | + UT_TESTF_LIVE_TREE); + +/* Test device_is_on_pci_bus() */ +static int dm_test_pci_on_bus(struct unit_test_state *uts) +{ + struct udevice *dev; + + ut_assertok(dm_pci_bus_find_bdf(PCI_BDF(0, 0x1f, 0), &dev)); + ut_asserteq(true, device_is_on_pci_bus(dev)); + ut_asserteq(false, device_is_on_pci_bus(dev_get_parent(dev))); + ut_asserteq(true, device_is_on_pci_bus(dev)); + + return 0; +} +DM_TEST(dm_test_pci_on_bus, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); + +/* + * Test support for multiple memory regions enabled via + * CONFIG_PCI_REGION_MULTI_ENTRY. When this feature is not enabled, + * only the last region of one type is stored. In this test-case, + * we have 2 memory regions, the first at 0x3000.0000 and the 2nd + * at 0x3100.0000. A correct test results now in BAR1 located at + * 0x3000.0000. + */ +static int dm_test_pci_region_multi(struct unit_test_state *uts) +{ + struct udevice *dev; + ulong mem_addr; + + /* Test memory BAR1 on bus#1 */ + ut_assertok(dm_pci_bus_find_bdf(PCI_BDF(1, 0x08, 0), &dev)); + mem_addr = dm_pci_read_bar32(dev, 1); + ut_asserteq(mem_addr, 0x30000000); + + return 0; +} +DM_TEST(dm_test_pci_region_multi, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); diff --git a/roms/u-boot/test/dm/pci_ep.c b/roms/u-boot/test/dm/pci_ep.c new file mode 100644 index 000000000..9b03b8bae --- /dev/null +++ b/roms/u-boot/test/dm/pci_ep.c @@ -0,0 +1,65 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2019 Ramon Fried + */ + +#include <common.h> +#include <dm.h> +#include <hexdump.h> +#include <pci_ep.h> +#include <asm/io.h> +#include <asm/test.h> +#include <dm/test.h> +#include <test/test.h> +#include <test/ut.h> + +/* Test that sandbox PCI EP works correctly */ +static int dm_test_pci_ep_base(struct unit_test_state *uts) +{ + struct udevice *bus; + struct pci_bar tmp_bar; + struct pci_ep_header tmp_header; + int i; + + struct pci_ep_header ep_header = { + .vendorid = 0x1234, + .deviceid = 0x2020, + .revid = 1, + .interrupt_pin = PCI_INTERRUPT_INTA, + }; + + struct pci_bar bar = { + .phys_addr = 0x80000000, + .size = 0x100000, + .barno = BAR_0, + .flags = PCI_BASE_ADDRESS_MEM_TYPE_64 | + PCI_BASE_ADDRESS_MEM_PREFETCH, + }; + + ut_assertok(uclass_get_device(UCLASS_PCI_EP, 0, &bus)); + ut_assertnonnull(bus); + + ut_assertok(pci_ep_write_header(bus, 0, &ep_header)); + ut_assertok(pci_ep_read_header(bus, 0, &tmp_header)); + ut_asserteq_mem(&tmp_header, &ep_header, sizeof(ep_header)); + + ut_assertok(pci_ep_set_msi(bus, 0, 4)); + ut_asserteq(pci_ep_get_msi(bus, 0), 4); + + ut_assertok(pci_ep_set_msix(bus, 0, 360)); + ut_asserteq(pci_ep_get_msix(bus, 0), 360); + + ut_assertok(pci_ep_set_bar(bus, 0, &bar)); + + ut_assertok(pci_ep_read_bar(bus, 0, &tmp_bar, BAR_0)); + ut_asserteq_mem(&tmp_bar, &bar, sizeof(bar)); + + for (i = 0; i < 10; i++) + ut_assertok(pci_ep_raise_irq(bus, 0, 1, PCI_EP_IRQ_LEGACY)); + + ut_asserteq(sandbox_get_pci_ep_irq_count(bus), 10); + return 0; +} + +DM_TEST(dm_test_pci_ep_base, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); + diff --git a/roms/u-boot/test/dm/phy.c b/roms/u-boot/test/dm/phy.c new file mode 100644 index 000000000..ecbd47bf1 --- /dev/null +++ b/roms/u-boot/test/dm/phy.c @@ -0,0 +1,147 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2017 Texas Instruments Incorporated - http://www.ti.com/ + * Written by Jean-Jacques Hiblot <jjhiblot@ti.com> + */ + +#include <common.h> +#include <dm.h> +#include <generic-phy.h> +#include <log.h> +#include <dm/test.h> +#include <test/test.h> +#include <test/ut.h> + +/* Base test of the phy uclass */ +static int dm_test_phy_base(struct unit_test_state *uts) +{ + struct udevice *dev; + struct phy phy1_method1; + struct phy phy1_method2; + struct phy phy2; + struct phy phy3; + struct udevice *parent; + + /* Get the device using the phy device*/ + ut_assertok(uclass_get_device_by_name(UCLASS_SIMPLE_BUS, + "gen_phy_user", &parent)); + /* + * Get the same phy port in 2 different ways and compare. + */ + ut_assertok(generic_phy_get_by_name(parent, "phy1", &phy1_method1)) + ut_assertok(generic_phy_get_by_index(parent, 0, &phy1_method2)) + ut_asserteq(phy1_method1.id, phy1_method2.id); + + /* + * Get the second phy port. Check that the same phy provider (device) + * provides this 2nd phy port, but that the IDs are different + */ + ut_assertok(generic_phy_get_by_name(parent, "phy2", &phy2)) + ut_asserteq_ptr(phy1_method2.dev, phy2.dev); + ut_assert(phy1_method1.id != phy2.id); + + /* + * Get the third phy port. Check that the phy provider is different + */ + ut_assertok(generic_phy_get_by_name(parent, "phy3", &phy3)) + ut_assert(phy2.dev != phy3.dev); + + /* Try to get a non-existing phy */ + ut_asserteq(-ENODEV, uclass_get_device(UCLASS_PHY, 4, &dev)); + ut_asserteq(-ENODATA, generic_phy_get_by_name(parent, + "phy_not_existing", &phy1_method1)); + + return 0; +} +DM_TEST(dm_test_phy_base, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); + +/* Test of the phy uclass using the sandbox phy driver operations */ +static int dm_test_phy_ops(struct unit_test_state *uts) +{ + struct phy phy1; + struct phy phy2; + struct phy phy3; + struct udevice *parent; + + ut_assertok(uclass_get_device_by_name(UCLASS_SIMPLE_BUS, + "gen_phy_user", &parent)); + + ut_assertok(generic_phy_get_by_name(parent, "phy1", &phy1)); + ut_asserteq(0, phy1.id); + ut_assertok(generic_phy_get_by_name(parent, "phy2", &phy2)); + ut_asserteq(1, phy2.id); + ut_assertok(generic_phy_get_by_name(parent, "phy3", &phy3)); + ut_asserteq(0, phy3.id); + + /* test normal operations */ + ut_assertok(generic_phy_init(&phy1)); + ut_assertok(generic_phy_power_on(&phy1)); + ut_assertok(generic_phy_power_off(&phy1)); + + /* + * test operations after exit(). + * The sandbox phy driver does not allow it. + */ + ut_assertok(generic_phy_exit(&phy1)); + ut_assert(generic_phy_power_on(&phy1) != 0); + ut_assert(generic_phy_power_off(&phy1) != 0); + + /* + * test normal operations again (after re-init) + */ + ut_assertok(generic_phy_init(&phy1)); + ut_assertok(generic_phy_power_on(&phy1)); + ut_assertok(generic_phy_power_off(&phy1)); + + /* + * test calling unimplemented feature. + * The call is expected to succeed + */ + ut_assertok(generic_phy_reset(&phy1)); + + /* PHY2 has a known problem with power off */ + ut_assertok(generic_phy_init(&phy2)); + ut_assertok(generic_phy_power_on(&phy2)); + ut_asserteq(-EIO, generic_phy_power_off(&phy2)); + + /* PHY3 has a known problem with power off and power on */ + ut_assertok(generic_phy_init(&phy3)); + ut_asserteq(-EIO, generic_phy_power_off(&phy3)); + ut_asserteq(-EIO, generic_phy_power_off(&phy3)); + + return 0; +} +DM_TEST(dm_test_phy_ops, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); + +static int dm_test_phy_bulk(struct unit_test_state *uts) +{ + struct phy_bulk phys; + struct udevice *parent; + + /* test normal operations */ + ut_assertok(uclass_get_device_by_name(UCLASS_SIMPLE_BUS, + "gen_phy_user1", &parent)); + + ut_assertok(generic_phy_get_bulk(parent, &phys)); + ut_asserteq(2, phys.count); + + ut_asserteq(0, generic_phy_init_bulk(&phys)); + ut_asserteq(0, generic_phy_power_on_bulk(&phys)); + ut_asserteq(0, generic_phy_power_off_bulk(&phys)); + ut_asserteq(0, generic_phy_exit_bulk(&phys)); + + /* has a known problem phy */ + ut_assertok(uclass_get_device_by_name(UCLASS_SIMPLE_BUS, + "gen_phy_user", &parent)); + + ut_assertok(generic_phy_get_bulk(parent, &phys)); + ut_asserteq(3, phys.count); + + ut_asserteq(0, generic_phy_init_bulk(&phys)); + ut_asserteq(-EIO, generic_phy_power_on_bulk(&phys)); + ut_asserteq(-EIO, generic_phy_power_off_bulk(&phys)); + ut_asserteq(0, generic_phy_exit_bulk(&phys)); + + return 0; +} +DM_TEST(dm_test_phy_bulk, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); diff --git a/roms/u-boot/test/dm/phys2bus.c b/roms/u-boot/test/dm/phys2bus.c new file mode 100644 index 000000000..342f2fa8e --- /dev/null +++ b/roms/u-boot/test/dm/phys2bus.c @@ -0,0 +1,37 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (c) 2020 Nicolas Saenz Julienne <nsaenzjulienne@suse.de> + */ + +#include <common.h> +#include <dm.h> +#include <mapmem.h> +#include <phys2bus.h> +#include <dm/device.h> +#include <dm/ofnode.h> +#include <dm/root.h> +#include <dm/test.h> +#include <dm/uclass-internal.h> +#include <test/ut.h> + +static int dm_test_phys_to_bus(struct unit_test_state *uts) +{ + struct udevice *dev; + ofnode node; + + node = ofnode_path("/mmio-bus@0"); + ut_assert(ofnode_valid(node)); + ut_assertok(uclass_get_device_by_ofnode(UCLASS_TEST_BUS, node, &dev)); + /* In this case it should be transparent, no dma-ranges in parent bus */ + ut_asserteq_addr((void*)0xfffffULL, (void*)dev_phys_to_bus(dev, 0xfffff)); + ut_asserteq_addr((void*)0xfffffULL, (void*)(ulong)dev_bus_to_phys(dev, 0xfffff)); + + node = ofnode_path("/mmio-bus@0/subnode@0"); + ut_assert(ofnode_valid(node)); + ut_assertok(uclass_get_device_by_ofnode(UCLASS_TEST_FDT, node, &dev)); + ut_asserteq_addr((void*)0x100fffffULL, (void*)dev_phys_to_bus(dev, 0xfffff)); + ut_asserteq_addr((void*)0xfffffULL, (void*)(ulong)dev_bus_to_phys(dev, 0x100fffff)); + + return 0; +} +DM_TEST(dm_test_phys_to_bus, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); diff --git a/roms/u-boot/test/dm/pinmux.c b/roms/u-boot/test/dm/pinmux.c new file mode 100644 index 000000000..265df4ccb --- /dev/null +++ b/roms/u-boot/test/dm/pinmux.c @@ -0,0 +1,138 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2020 Sean Anderson <seanga2@gmail.com> + */ + +#include <common.h> +#include <dm.h> +#include <dm/pinctrl.h> +#include <dm/test.h> +#include <test/ut.h> + +static char buf[64]; +#define test_muxing(selector, expected) do { \ + ut_assertok(pinctrl_get_pin_muxing(dev, selector, buf, sizeof(buf))); \ + ut_asserteq_str(expected, (char *)&buf); \ +} while (0) + +#define test_name(selector, expected) do { \ + ut_assertok(pinctrl_get_pin_name(dev, selector, buf, sizeof(buf))); \ + ut_asserteq_str(expected, (char *)&buf); \ +} while (0) + +static int dm_test_pinmux(struct unit_test_state *uts) +{ + struct udevice *dev; + + ut_assertok(uclass_get_device_by_name(UCLASS_PINCTRL, "pinctrl", &dev)); + test_muxing(0, "UART TX."); + test_muxing(1, "UART RX."); + test_muxing(2, "I2S SCK."); + test_muxing(3, "I2S SD."); + test_muxing(4, "I2S WS."); + test_muxing(5, "GPIO0 bias-pull-up input-disable."); + test_muxing(6, "GPIO1 drive-open-drain."); + test_muxing(7, "GPIO2 bias-pull-down input-enable."); + test_muxing(8, "GPIO3 bias-disable."); + + ut_assertok(pinctrl_select_state(dev, "alternate")); + test_muxing(0, "I2C SCL drive-open-drain."); + test_muxing(1, "I2C SDA drive-open-drain."); + test_muxing(2, "SPI SCLK."); + test_muxing(3, "SPI MOSI."); + test_muxing(4, "SPI MISO."); + test_muxing(5, "SPI CS0."); + test_muxing(6, "SPI CS1."); + test_muxing(7, "GPIO2 bias-pull-down input-enable."); + test_muxing(8, "GPIO3 bias-disable."); + + ut_assertok(pinctrl_select_state(dev, "0")); + test_muxing(0, "I2C SCL drive-open-drain."); + test_muxing(1, "I2C SDA drive-open-drain."); + test_muxing(2, "I2S SCK."); + test_muxing(3, "I2S SD."); + test_muxing(4, "I2S WS."); + test_muxing(5, "GPIO0 bias-pull-up input-disable."); + test_muxing(6, "GPIO1 drive-open-drain."); + test_muxing(7, "GPIO2 bias-pull-down input-enable."); + test_muxing(8, "GPIO3 bias-disable."); + + return 0; +} + +DM_TEST(dm_test_pinmux, UT_TESTF_SCAN_FDT); + +static int dm_test_pinctrl_single(struct unit_test_state *uts) +{ + struct udevice *dev; + int ret; + + ret = uclass_get_device_by_name(UCLASS_PINCTRL, + "pinctrl-single-no-width", &dev); + ut_asserteq(-EINVAL, ret); + ut_assertok(uclass_get_device_by_name(UCLASS_PWM, "pwm", &dev)); + ut_assertok(uclass_get_device_by_name(UCLASS_SERIAL, "serial", &dev)); + ut_assertok(uclass_get_device_by_name(UCLASS_SPI, "spi@0", &dev)); + ut_assertok(uclass_get_device_by_name(UCLASS_PINCTRL, + "pinctrl-single-pins", &dev)); + ut_asserteq(142, pinctrl_get_pins_count(dev)); + test_name(0, "PIN0"); + test_name(141, "PIN141"); + test_name(142, "Error"); + test_muxing(0, "0x00000000 0x00000000 UNCLAIMED"); + test_muxing(18, "0x00000048 0x00000006 pinmux_pwm_pins"); + test_muxing(28, "0x00000070 0x00000030 pinmux_uart0_pins"); + test_muxing(29, "0x00000074 0x00000000 pinmux_uart0_pins"); + test_muxing(100, "0x00000190 0x0000000c pinmux_spi0_pins"); + test_muxing(101, "0x00000194 0x0000000c pinmux_spi0_pins"); + test_muxing(102, "0x00000198 0x00000023 pinmux_spi0_pins"); + test_muxing(103, "0x0000019c 0x0000000c pinmux_spi0_pins"); + ret = pinctrl_get_pin_muxing(dev, 142, buf, sizeof(buf)); + ut_asserteq(-EINVAL, ret); + ut_assertok(uclass_get_device_by_name(UCLASS_I2C, "i2c@0", &dev)); + ut_assertok(uclass_get_device_by_name(UCLASS_VIDEO, "lcd", &dev)); + ut_assertok(uclass_get_device_by_name(UCLASS_PINCTRL, + "pinctrl-single-bits", &dev)); + ut_asserteq(160, pinctrl_get_pins_count(dev)); + test_name(0, "PIN0"); + test_name(159, "PIN159"); + test_name(160, "Error"); + test_muxing(0, "0x00000000 0x00000000 UNCLAIMED"); + test_muxing(34, "0x00000010 0x00000200 pinmux_i2c0_pins"); + test_muxing(35, "0x00000010 0x00002000 pinmux_i2c0_pins"); + test_muxing(130, "0x00000040 0x00000200 pinmux_lcd_pins"); + test_muxing(131, "0x00000040 0x00002000 pinmux_lcd_pins"); + test_muxing(132, "0x00000040 0x00020000 pinmux_lcd_pins"); + test_muxing(133, "0x00000040 0x00200000 pinmux_lcd_pins"); + test_muxing(134, "0x00000040 0x02000000 pinmux_lcd_pins"); + test_muxing(135, "0x00000040 0x20000000 pinmux_lcd_pins"); + test_muxing(136, "0x00000044 0x00000002 pinmux_lcd_pins"); + test_muxing(137, "0x00000044 0x00000020 pinmux_lcd_pins"); + test_muxing(138, "0x00000044 0x00000200 pinmux_lcd_pins"); + test_muxing(139, "0x00000044 0x00002000 pinmux_lcd_pins"); + test_muxing(140, "0x00000044 0x00020000 pinmux_lcd_pins"); + test_muxing(141, "0x00000044 0x00200000 pinmux_lcd_pins"); + test_muxing(142, "0x00000044 0x02000000 pinmux_lcd_pins"); + test_muxing(143, "0x00000044 0x20000000 pinmux_lcd_pins"); + test_muxing(144, "0x00000048 0x00000002 pinmux_lcd_pins"); + test_muxing(145, "0x00000048 0x00000020 pinmux_lcd_pins"); + test_muxing(146, "0x00000048 0x00000000 UNCLAIMED"); + test_muxing(147, "0x00000048 0x00000000 UNCLAIMED"); + test_muxing(148, "0x00000048 0x00000000 UNCLAIMED"); + test_muxing(149, "0x00000048 0x00000000 UNCLAIMED"); + test_muxing(150, "0x00000048 0x02000000 pinmux_lcd_pins"); + test_muxing(151, "0x00000048 0x00000000 UNCLAIMED"); + test_muxing(152, "0x0000004c 0x00000002 pinmux_lcd_pins"); + test_muxing(153, "0x0000004c 0x00000020 pinmux_lcd_pins"); + test_muxing(154, "0x0000004c 0x00000000 UNCLAIMED"); + test_muxing(155, "0x0000004c 0x00000000 UNCLAIMED"); + test_muxing(156, "0x0000004c 0x00000000 UNCLAIMED"); + test_muxing(157, "0x0000004c 0x00000000 UNCLAIMED"); + test_muxing(158, "0x0000004c 0x02000000 pinmux_lcd_pins"); + test_muxing(159, "0x0000004c 0x00000000 UNCLAIMED"); + ret = pinctrl_get_pin_muxing(dev, 160, buf, sizeof(buf)); + ut_asserteq(-EINVAL, ret); + return 0; +} + +DM_TEST(dm_test_pinctrl_single, UT_TESTF_SCAN_FDT); diff --git a/roms/u-boot/test/dm/pmc.c b/roms/u-boot/test/dm/pmc.c new file mode 100644 index 000000000..e70227e78 --- /dev/null +++ b/roms/u-boot/test/dm/pmc.c @@ -0,0 +1,33 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Test for power-management controller uclass (PMC) + * + * Copyright 2019 Google LLC + */ + +#include <common.h> +#include <dm.h> +#include <power/acpi_pmc.h> +#include <dm/test.h> +#include <test/ut.h> + +/* Base test of the PMC uclass */ +static int dm_test_pmc_base(struct unit_test_state *uts) +{ + struct acpi_pmc_upriv *upriv; + struct udevice *dev; + + ut_assertok(uclass_first_device_err(UCLASS_ACPI_PMC, &dev)); + + ut_assertok(pmc_disable_tco(dev)); + ut_assertok(pmc_init(dev)); + ut_assertok(pmc_prev_sleep_state(dev)); + + /* Check some values to see that I/O works */ + upriv = dev_get_uclass_priv(dev); + ut_asserteq(0x24, upriv->gpe0_sts[1]); + ut_asserteq(0x64, upriv->tco1_sts); + + return 0; +} +DM_TEST(dm_test_pmc_base, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); diff --git a/roms/u-boot/test/dm/pmic.c b/roms/u-boot/test/dm/pmic.c new file mode 100644 index 000000000..ce671202f --- /dev/null +++ b/roms/u-boot/test/dm/pmic.c @@ -0,0 +1,131 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Tests for the driver model pmic API + * + * Copyright (c) 2015 Samsung Electronics + * Przemyslaw Marczak <p.marczak@samsung.com> + */ + +#include <common.h> +#include <errno.h> +#include <dm.h> +#include <fdtdec.h> +#include <fsl_pmic.h> +#include <malloc.h> +#include <dm/device-internal.h> +#include <dm/root.h> +#include <dm/test.h> +#include <dm/uclass-internal.h> +#include <dm/util.h> +#include <power/pmic.h> +#include <power/sandbox_pmic.h> +#include <test/test.h> +#include <test/ut.h> + +/* Test PMIC get method */ + +static inline int power_pmic_get(struct unit_test_state *uts, char *name) +{ + struct udevice *dev; + + ut_assertok(pmic_get(name, &dev)); + ut_assertnonnull(dev); + + /* Check PMIC's name */ + ut_asserteq_str(name, dev->name); + + return 0; +} + +/* Test PMIC get method */ +static int dm_test_power_pmic_get(struct unit_test_state *uts) +{ + power_pmic_get(uts, "sandbox_pmic"); + + return 0; +} +DM_TEST(dm_test_power_pmic_get, UT_TESTF_SCAN_FDT); + +/* PMIC get method - MC34708 - for 3 bytes transmission */ +static int dm_test_power_pmic_mc34708_get(struct unit_test_state *uts) +{ + power_pmic_get(uts, "pmic@41"); + + return 0; +} + +DM_TEST(dm_test_power_pmic_mc34708_get, UT_TESTF_SCAN_FDT); + +/* Test PMIC I/O */ +static int dm_test_power_pmic_io(struct unit_test_state *uts) +{ + const char *name = "sandbox_pmic"; + uint8_t out_buffer, in_buffer; + struct udevice *dev; + int reg_count, i; + + ut_assertok(pmic_get(name, &dev)); + + reg_count = pmic_reg_count(dev); + ut_asserteq(reg_count, SANDBOX_PMIC_REG_COUNT); + + /* + * Test PMIC I/O - write and read a loop counter. + * usually we can't write to all PMIC's registers in the real hardware, + * but we can to the sandbox pmic. + */ + for (i = 0; i < reg_count; i++) { + out_buffer = i; + ut_assertok(pmic_write(dev, i, &out_buffer, 1)); + ut_assertok(pmic_read(dev, i, &in_buffer, 1)); + ut_asserteq(out_buffer, in_buffer); + } + + return 0; +} +DM_TEST(dm_test_power_pmic_io, UT_TESTF_SCAN_FDT); + +#define MC34708_PMIC_REG_COUNT 64 +#define MC34708_PMIC_TEST_VAL 0x125534 +static int dm_test_power_pmic_mc34708_regs_check(struct unit_test_state *uts) +{ + struct udevice *dev; + int reg_count; + + ut_assertok(pmic_get("pmic@41", &dev)); + + /* Check number of PMIC registers */ + reg_count = pmic_reg_count(dev); + ut_asserteq(reg_count, MC34708_PMIC_REG_COUNT); + + return 0; +} + +DM_TEST(dm_test_power_pmic_mc34708_regs_check, UT_TESTF_SCAN_FDT); + +static int dm_test_power_pmic_mc34708_rw_val(struct unit_test_state *uts) +{ + struct udevice *dev; + int val; + + ut_assertok(pmic_get("pmic@41", &dev)); + + /* Check if single 3 byte read is successful */ + val = pmic_reg_read(dev, REG_POWER_CTL2); + ut_asserteq(val, 0x422100); + + /* Check if RW works */ + val = 0; + ut_assertok(pmic_reg_write(dev, REG_RTC_TIME, val)); + ut_assertok(pmic_reg_write(dev, REG_RTC_TIME, MC34708_PMIC_TEST_VAL)); + val = pmic_reg_read(dev, REG_RTC_TIME); + ut_asserteq(val, MC34708_PMIC_TEST_VAL); + + pmic_clrsetbits(dev, REG_POWER_CTL2, 0x3 << 8, 1 << 9); + val = pmic_reg_read(dev, REG_POWER_CTL2); + ut_asserteq(val, (0x422100 & ~(0x3 << 8)) | (1 << 9)); + + return 0; +} + +DM_TEST(dm_test_power_pmic_mc34708_rw_val, UT_TESTF_SCAN_FDT); diff --git a/roms/u-boot/test/dm/power-domain.c b/roms/u-boot/test/dm/power-domain.c new file mode 100644 index 000000000..8604b5d72 --- /dev/null +++ b/roms/u-boot/test/dm/power-domain.c @@ -0,0 +1,49 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2016, NVIDIA CORPORATION. + */ + +#include <common.h> +#include <dm.h> +#include <malloc.h> +#include <dm/test.h> +#include <asm/power-domain.h> +#include <test/test.h> +#include <test/ut.h> + +/* This must match the specifier for power-domains in the DT node */ +#define TEST_POWER_DOMAIN 2 + +static int dm_test_power_domain(struct unit_test_state *uts) +{ + struct udevice *dev_power_domain; + struct udevice *dev_test; + + ut_assertok(uclass_get_device_by_name(UCLASS_POWER_DOMAIN, + "power-domain", + &dev_power_domain)); + ut_asserteq(0, sandbox_power_domain_query(dev_power_domain, 0)); + ut_asserteq(0, sandbox_power_domain_query(dev_power_domain, + TEST_POWER_DOMAIN)); + + ut_assertok(uclass_get_device_by_name(UCLASS_MISC, "power-domain-test", + &dev_test)); + ut_asserteq(1, sandbox_power_domain_query(dev_power_domain, + TEST_POWER_DOMAIN)); + ut_assertok(sandbox_power_domain_test_get(dev_test)); + + ut_assertok(sandbox_power_domain_test_on(dev_test)); + ut_asserteq(0, sandbox_power_domain_query(dev_power_domain, 0)); + ut_asserteq(1, sandbox_power_domain_query(dev_power_domain, + TEST_POWER_DOMAIN)); + + ut_assertok(sandbox_power_domain_test_off(dev_test)); + ut_asserteq(0, sandbox_power_domain_query(dev_power_domain, 0)); + ut_asserteq(0, sandbox_power_domain_query(dev_power_domain, + TEST_POWER_DOMAIN)); + + ut_assertok(sandbox_power_domain_test_free(dev_test)); + + return 0; +} +DM_TEST(dm_test_power_domain, UT_TESTF_SCAN_FDT); diff --git a/roms/u-boot/test/dm/pwm.c b/roms/u-boot/test/dm/pwm.c new file mode 100644 index 000000000..b624cf3d6 --- /dev/null +++ b/roms/u-boot/test/dm/pwm.c @@ -0,0 +1,43 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2017 Google, Inc + */ + +#include <common.h> +#include <dm.h> +#include <pwm.h> +#include <asm/test.h> +#include <dm/test.h> +#include <test/test.h> +#include <test/ut.h> + +/* Basic test of the pwm uclass */ +static int dm_test_pwm_base(struct unit_test_state *uts) +{ + struct udevice *dev; + uint period_ns; + uint duty_ns; + bool enable; + bool polarity; + + ut_assertok(uclass_get_device(UCLASS_PWM, 0, &dev)); + ut_assertnonnull(dev); + ut_assertok(pwm_set_config(dev, 0, 100, 50)); + ut_assertok(pwm_set_enable(dev, 0, true)); + ut_assertok(pwm_set_enable(dev, 1, true)); + ut_assertok(pwm_set_enable(dev, 2, true)); + ut_asserteq(-ENOSPC, pwm_set_enable(dev, 3, true)); + ut_assertok(pwm_set_invert(dev, 0, true)); + + ut_assertok(pwm_set_config(dev, 2, 100, 50)); + ut_assertok(sandbox_pwm_get_config(dev, 2, &period_ns, &duty_ns, + &enable, &polarity)); + ut_asserteq(period_ns, 4096); + ut_asserteq(duty_ns, 50 * 4096 / 100); + + ut_assertok(uclass_get_device(UCLASS_PWM, 1, &dev)); + ut_asserteq(-ENODEV, uclass_get_device(UCLASS_PWM, 2, &dev)); + + return 0; +} +DM_TEST(dm_test_pwm_base, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); diff --git a/roms/u-boot/test/dm/qfw.c b/roms/u-boot/test/dm/qfw.c new file mode 100644 index 000000000..f3f356898 --- /dev/null +++ b/roms/u-boot/test/dm/qfw.c @@ -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); diff --git a/roms/u-boot/test/dm/ram.c b/roms/u-boot/test/dm/ram.c new file mode 100644 index 000000000..f62434313 --- /dev/null +++ b/roms/u-boot/test/dm/ram.c @@ -0,0 +1,29 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2015 Google, Inc + */ + +#include <common.h> +#include <dm.h> +#include <ram.h> +#include <asm/global_data.h> +#include <dm/test.h> +#include <test/test.h> +#include <test/ut.h> + +DECLARE_GLOBAL_DATA_PTR; + +/* Basic test of the ram uclass */ +static int dm_test_ram_base(struct unit_test_state *uts) +{ + struct udevice *dev; + struct ram_info info; + + ut_assertok(uclass_get_device(UCLASS_RAM, 0, &dev)); + ut_assertok(ram_get_info(dev, &info)); + ut_asserteq(0, info.base); + ut_asserteq(gd->ram_size, info.size); + + return 0; +} +DM_TEST(dm_test_ram_base, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); diff --git a/roms/u-boot/test/dm/read.c b/roms/u-boot/test/dm/read.c new file mode 100644 index 000000000..7768aa296 --- /dev/null +++ b/roms/u-boot/test/dm/read.c @@ -0,0 +1,49 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (c) 2020 Nicolas Saenz Julienne <nsaenzjulienne@suse.de> + */ + +#include <common.h> +#include <dm.h> +#include <dm/device.h> +#include <dm/ofnode.h> +#include <dm/root.h> +#include <dm/test.h> +#include <dm/uclass-internal.h> +#include <test/ut.h> + +static int dm_test_dma_ranges(struct unit_test_state *uts) +{ + struct udevice *dev; + phys_addr_t cpu; + dma_addr_t bus; + ofnode node; + u64 size; + + /* dma-ranges are on the device's node */ + node = ofnode_path("/mmio-bus@0"); + ut_assert(ofnode_valid(node)); + ut_assertok(uclass_get_device_by_ofnode(UCLASS_TEST_BUS, node, &dev)); + ut_assertok(dev_get_dma_range(dev, &cpu, &bus, &size)); + ut_asserteq_64(0x40000, size); + ut_asserteq_64(0x0, cpu); + ut_asserteq_64(0x10000000, bus); + + /* dma-ranges are on the bus' node */ + node = ofnode_path("/mmio-bus@0/subnode@0"); + ut_assert(ofnode_valid(node)); + ut_assertok(uclass_get_device_by_ofnode(UCLASS_TEST_FDT, node, &dev)); + ut_assertok(dev_get_dma_range(dev, &cpu, &bus, &size)); + ut_asserteq_64(0x40000, size); + ut_asserteq_64(0x0, cpu); + ut_asserteq_64(0x10000000, bus); + + /* No dma-ranges available */ + node = ofnode_path("/mmio-bus@1"); + ut_assert(ofnode_valid(node)); + ut_assertok(uclass_get_device_by_ofnode(UCLASS_TEST_BUS, node, &dev)); + ut_asserteq(-ENOENT, dev_get_dma_range(dev, &cpu, &bus, &size)); + + return 0; +} +DM_TEST(dm_test_dma_ranges, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); diff --git a/roms/u-boot/test/dm/regmap.c b/roms/u-boot/test/dm/regmap.c new file mode 100644 index 000000000..04bb1645d --- /dev/null +++ b/roms/u-boot/test/dm/regmap.c @@ -0,0 +1,387 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2015 Google, Inc + */ + +#include <common.h> +#include <dm.h> +#include <log.h> +#include <mapmem.h> +#include <regmap.h> +#include <syscon.h> +#include <rand.h> +#include <asm/test.h> +#include <dm/test.h> +#include <dm/devres.h> +#include <linux/err.h> +#include <test/test.h> +#include <test/ut.h> + +/* Base test of register maps */ +static int dm_test_regmap_base(struct unit_test_state *uts) +{ + struct udevice *dev; + struct regmap *map; + ofnode node; + int i; + + ut_assertok(uclass_get_device(UCLASS_SYSCON, 0, &dev)); + map = syscon_get_regmap(dev); + ut_assertok_ptr(map); + ut_asserteq(1, map->range_count); + ut_asserteq(0x10, map->ranges[0].start); + ut_asserteq(16, map->ranges[0].size); + ut_asserteq(0x10, map_to_sysmem(regmap_get_range(map, 0))); + + ut_assertok(uclass_get_device(UCLASS_SYSCON, 1, &dev)); + map = syscon_get_regmap(dev); + ut_assertok_ptr(map); + ut_asserteq(4, map->range_count); + ut_asserteq(0x20, map->ranges[0].start); + for (i = 0; i < 4; i++) { + const unsigned long addr = 0x20 + 8 * i; + + ut_asserteq(addr, map->ranges[i].start); + ut_asserteq(5 + i, map->ranges[i].size); + ut_asserteq(addr, map_to_sysmem(regmap_get_range(map, i))); + } + + /* Check that we can't pretend a different device is a syscon */ + ut_assertok(uclass_get_device(UCLASS_I2C, 0, &dev)); + map = syscon_get_regmap(dev); + ut_asserteq_ptr(ERR_PTR(-ENOEXEC), map); + + /* A different device can be a syscon by using Linux-compat API */ + node = ofnode_path("/syscon@2"); + ut_assert(ofnode_valid(node)); + + map = syscon_node_to_regmap(node); + ut_assertok_ptr(map); + ut_asserteq(4, map->range_count); + ut_asserteq(0x40, map->ranges[0].start); + for (i = 0; i < 4; i++) { + const unsigned long addr = 0x40 + 8 * i; + + ut_asserteq(addr, map->ranges[i].start); + ut_asserteq(5 + i, map->ranges[i].size); + ut_asserteq(addr, map_to_sysmem(regmap_get_range(map, i))); + } + + return 0; +} +DM_TEST(dm_test_regmap_base, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); + +/* Test we can access a regmap through syscon */ +static int dm_test_regmap_syscon(struct unit_test_state *uts) +{ + struct regmap *map; + + map = syscon_get_regmap_by_driver_data(SYSCON0); + ut_assertok_ptr(map); + ut_asserteq(1, map->range_count); + + map = syscon_get_regmap_by_driver_data(SYSCON1); + ut_assertok_ptr(map); + ut_asserteq(4, map->range_count); + + map = syscon_get_regmap_by_driver_data(SYSCON_COUNT); + ut_asserteq_ptr(ERR_PTR(-ENODEV), map); + + ut_asserteq(0x10, map_to_sysmem(syscon_get_first_range(SYSCON0))); + ut_asserteq(0x20, map_to_sysmem(syscon_get_first_range(SYSCON1))); + ut_asserteq_ptr(ERR_PTR(-ENODEV), + syscon_get_first_range(SYSCON_COUNT)); + + return 0; +} + +DM_TEST(dm_test_regmap_syscon, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); + +/* Read/Write/Modify test */ +static int dm_test_regmap_rw(struct unit_test_state *uts) +{ + struct udevice *dev; + struct regmap *map; + uint reg; + + sandbox_set_enable_memio(true); + ut_assertok(uclass_get_device(UCLASS_SYSCON, 0, &dev)); + map = syscon_get_regmap(dev); + ut_assertok_ptr(map); + + ut_assertok(regmap_write(map, 0, 0xcacafafa)); + ut_assertok(regmap_write(map, 5, 0x55aa2211)); + + ut_assertok(regmap_read(map, 0, ®)); + ut_asserteq(0xcacafafa, reg); + ut_assertok(regmap_read(map, 5, ®)); + ut_asserteq(0x55aa2211, reg); + + ut_assertok(regmap_read(map, 0, ®)); + ut_asserteq(0xcacafafa, reg); + ut_assertok(regmap_update_bits(map, 0, 0xff00ff00, 0x55aa2211)); + ut_assertok(regmap_read(map, 0, ®)); + ut_asserteq(0x55ca22fa, reg); + ut_assertok(regmap_update_bits(map, 5, 0x00ff00ff, 0xcacafada)); + ut_assertok(regmap_read(map, 5, ®)); + ut_asserteq(0x55ca22da, reg); + + return 0; +} + +DM_TEST(dm_test_regmap_rw, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); + +/* Get/Set test */ +static int dm_test_regmap_getset(struct unit_test_state *uts) +{ + struct udevice *dev; + struct regmap *map; + uint reg; + struct layout { + u32 val0; + u32 val1; + u32 val2; + u32 val3; + }; + + sandbox_set_enable_memio(true); + ut_assertok(uclass_get_device(UCLASS_SYSCON, 0, &dev)); + map = syscon_get_regmap(dev); + ut_assertok_ptr(map); + + regmap_set(map, struct layout, val0, 0xcacafafa); + regmap_set(map, struct layout, val3, 0x55aa2211); + + ut_assertok(regmap_get(map, struct layout, val0, ®)); + ut_asserteq(0xcacafafa, reg); + ut_assertok(regmap_get(map, struct layout, val3, ®)); + ut_asserteq(0x55aa2211, reg); + + return 0; +} + +DM_TEST(dm_test_regmap_getset, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); + +/* Read polling test */ +static int dm_test_regmap_poll(struct unit_test_state *uts) +{ + struct udevice *dev; + struct regmap *map; + uint reg; + unsigned long start; + + ut_assertok(uclass_get_device(UCLASS_SYSCON, 0, &dev)); + map = syscon_get_regmap(dev); + ut_assertok_ptr(map); + + start = get_timer(0); + + ut_assertok(regmap_write(map, 0, 0x0)); + ut_asserteq(-ETIMEDOUT, + regmap_read_poll_timeout_test(map, 0, reg, + (reg == 0xcacafafa), + 1, 5 * CONFIG_SYS_HZ, + 5 * CONFIG_SYS_HZ)); + + ut_assert(get_timer(start) > (5 * CONFIG_SYS_HZ)); + + return 0; +} + +DM_TEST(dm_test_regmap_poll, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); + +struct regmaptest_priv { + struct regmap *cfg_regmap; /* For testing regmap_config options. */ + struct regmap *fld_regmap; /* For testing regmap fields. */ + struct regmap_field **fields; +}; + +static const struct reg_field field_cfgs[] = { + { + .reg = 0, + .lsb = 0, + .msb = 6, + }, + { + .reg = 2, + .lsb = 4, + .msb = 12, + }, + { + .reg = 2, + .lsb = 12, + .msb = 15, + } +}; + +#define REGMAP_TEST_BUF_START 0 +#define REGMAP_TEST_BUF_SZ 5 + +static int remaptest_probe(struct udevice *dev) +{ + struct regmaptest_priv *priv = dev_get_priv(dev); + struct regmap *regmap; + struct regmap_field *field; + struct regmap_config cfg; + int i; + static const int n = ARRAY_SIZE(field_cfgs); + + /* + * To exercise all the regmap config options, create a regmap that + * points to a custom memory area instead of the one defined in device + * tree. Use 2-byte elements. To allow directly indexing into the + * elements, use an offset shift of 1. So, accessing offset 1 gets the + * element at index 1 at memory location 2. + * + * REGMAP_TEST_BUF_SZ is the number of elements, so we need to multiply + * it by 2 because r_size expects number of bytes. + */ + cfg.reg_offset_shift = 1; + cfg.r_start = REGMAP_TEST_BUF_START; + cfg.r_size = REGMAP_TEST_BUF_SZ * 2; + cfg.width = REGMAP_SIZE_16; + + regmap = devm_regmap_init(dev, NULL, NULL, &cfg); + if (IS_ERR(regmap)) + return PTR_ERR(regmap); + priv->cfg_regmap = regmap; + + memset(&cfg, 0, sizeof(struct regmap_config)); + cfg.width = REGMAP_SIZE_16; + + regmap = devm_regmap_init(dev, NULL, NULL, &cfg); + if (IS_ERR(regmap)) + return PTR_ERR(regmap); + priv->fld_regmap = regmap; + + priv->fields = devm_kzalloc(dev, sizeof(struct regmap_field *) * n, + GFP_KERNEL); + if (!priv->fields) + return -ENOMEM; + + for (i = 0 ; i < n; i++) { + field = devm_regmap_field_alloc(dev, priv->fld_regmap, + field_cfgs[i]); + if (IS_ERR(field)) + return PTR_ERR(field); + priv->fields[i] = field; + } + + return 0; +} + +static const struct udevice_id regmaptest_ids[] = { + { .compatible = "sandbox,regmap_test" }, + { } +}; + +U_BOOT_DRIVER(regmap_test) = { + .name = "regmaptest_drv", + .of_match = regmaptest_ids, + .id = UCLASS_NOP, + .probe = remaptest_probe, + .priv_auto = sizeof(struct regmaptest_priv), +}; + +static int dm_test_devm_regmap(struct unit_test_state *uts) +{ + int i = 0; + u16 val; + void *valp = &val; + u16 pattern[REGMAP_TEST_BUF_SZ]; + u16 *buffer; + struct udevice *dev; + struct regmaptest_priv *priv; + + sandbox_set_enable_memio(true); + + /* + * Map the memory area the regmap should point to so we can make sure + * the writes actually go to that location. + */ + buffer = map_physmem(REGMAP_TEST_BUF_START, + REGMAP_TEST_BUF_SZ * 2, MAP_NOCACHE); + + ut_assertok(uclass_get_device_by_name(UCLASS_NOP, "regmap-test_0", + &dev)); + priv = dev_get_priv(dev); + + for (i = 0; i < REGMAP_TEST_BUF_SZ; i++) { + pattern[i] = i * 0x87654321; + ut_assertok(regmap_write(priv->cfg_regmap, i, pattern[i])); + } + for (i = 0; i < REGMAP_TEST_BUF_SZ; i++) { + ut_assertok(regmap_read(priv->cfg_regmap, i, valp)); + ut_asserteq(val, buffer[i]); + ut_asserteq(val, pattern[i]); + } + + ut_asserteq(-ERANGE, regmap_write(priv->cfg_regmap, REGMAP_TEST_BUF_SZ, + val)); + ut_asserteq(-ERANGE, regmap_read(priv->cfg_regmap, REGMAP_TEST_BUF_SZ, + valp)); + ut_asserteq(-ERANGE, regmap_write(priv->cfg_regmap, -1, val)); + ut_asserteq(-ERANGE, regmap_read(priv->cfg_regmap, -1, valp)); + + return 0; +} +DM_TEST(dm_test_devm_regmap, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); + +static int test_one_field(struct unit_test_state *uts, + struct regmap *regmap, + struct regmap_field *field, + struct reg_field field_cfg) +{ + int j; + unsigned int val; + int mask = (1 << (field_cfg.msb - field_cfg.lsb + 1)) - 1; + int shift = field_cfg.lsb; + + ut_assertok(regmap_write(regmap, field_cfg.reg, 0)); + ut_assertok(regmap_read(regmap, field_cfg.reg, &val)); + ut_asserteq(0, val); + + for (j = 0; j <= mask; j++) { + ut_assertok(regmap_field_write(field, j)); + ut_assertok(regmap_field_read(field, &val)); + ut_asserteq(j, val); + ut_assertok(regmap_read(regmap, field_cfg.reg, &val)); + ut_asserteq(j << shift, val); + } + + ut_assertok(regmap_field_write(field, mask + 1)); + ut_assertok(regmap_read(regmap, field_cfg.reg, &val)); + ut_asserteq(0, val); + + ut_assertok(regmap_field_write(field, 0xFFFF)); + ut_assertok(regmap_read(regmap, field_cfg.reg, &val)); + ut_asserteq(mask << shift, val); + + ut_assertok(regmap_write(regmap, field_cfg.reg, 0xFFFF)); + ut_assertok(regmap_field_write(field, 0)); + ut_assertok(regmap_read(regmap, field_cfg.reg, &val)); + ut_asserteq(0xFFFF & ~(mask << shift), val); + return 0; +} + +static int dm_test_devm_regmap_field(struct unit_test_state *uts) +{ + int i, rc; + struct udevice *dev; + struct regmaptest_priv *priv; + + ut_assertok(uclass_get_device_by_name(UCLASS_NOP, "regmap-test_0", + &dev)); + priv = dev_get_priv(dev); + + sandbox_set_enable_memio(true); + for (i = 0 ; i < ARRAY_SIZE(field_cfgs); i++) { + rc = test_one_field(uts, priv->fld_regmap, priv->fields[i], + field_cfgs[i]); + if (rc) + break; + } + + return 0; +} +DM_TEST(dm_test_devm_regmap_field, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); diff --git a/roms/u-boot/test/dm/regulator.c b/roms/u-boot/test/dm/regulator.c new file mode 100644 index 000000000..86f4862d9 --- /dev/null +++ b/roms/u-boot/test/dm/regulator.c @@ -0,0 +1,404 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Tests for the driver model regulator API + * + * Copyright (c) 2015 Samsung Electronics + * Przemyslaw Marczak <p.marczak@samsung.com> + */ + +#include <common.h> +#include <errno.h> +#include <dm.h> +#include <fdtdec.h> +#include <log.h> +#include <malloc.h> +#include <dm/device-internal.h> +#include <dm/root.h> +#include <dm/util.h> +#include <dm/test.h> +#include <dm/uclass-internal.h> +#include <power/pmic.h> +#include <power/regulator.h> +#include <power/sandbox_pmic.h> +#include <test/test.h> +#include <test/ut.h> + +enum { + BUCK1, + BUCK2, + BUCK3, + LDO1, + LDO2, + OUTPUT_COUNT, +}; + +enum { + DEVNAME = 0, + PLATNAME, + OUTPUT_NAME_COUNT, +}; + +static const char *regulator_names[OUTPUT_COUNT][OUTPUT_NAME_COUNT] = { + /* devname, platname */ + { SANDBOX_BUCK1_DEVNAME, SANDBOX_BUCK1_PLATNAME }, + { SANDBOX_BUCK2_DEVNAME, SANDBOX_BUCK2_PLATNAME }, + { SANDBOX_BUCK3_DEVNAME, SANDBOX_BUCK3_PLATNAME }, + { SANDBOX_LDO1_DEVNAME, SANDBOX_LDO1_PLATNAME}, + { SANDBOX_LDO2_DEVNAME, SANDBOX_LDO2_PLATNAME}, +}; + +/* Test regulator get method */ +static int dm_test_power_regulator_get(struct unit_test_state *uts) +{ + struct dm_regulator_uclass_plat *uc_pdata; + struct udevice *dev_by_devname; + struct udevice *dev_by_platname; + const char *devname; + const char *platname; + int i; + + for (i = 0; i < OUTPUT_COUNT; i++) { + /* + * Do the test for each regulator's devname and platname, + * which are related to a single device. + */ + devname = regulator_names[i][DEVNAME]; + platname = regulator_names[i][PLATNAME]; + + /* + * Check, that regulator_get_by_devname() function, returns + * a device with the name equal to the requested one. + */ + ut_assertok(regulator_get_by_devname(devname, &dev_by_devname)); + ut_asserteq_str(devname, dev_by_devname->name); + + /* + * Check, that regulator_get_by_platname() function, returns + * a device with the name equal to the requested one. + */ + ut_assertok(regulator_get_by_platname(platname, &dev_by_platname)); + uc_pdata = dev_get_uclass_plat(dev_by_platname); + ut_assert(uc_pdata); + ut_asserteq_str(platname, uc_pdata->name); + + /* + * Check, that the pointers returned by both get functions, + * points to the same regulator device. + */ + ut_asserteq_ptr(dev_by_devname, dev_by_platname); + } + + return 0; +} +DM_TEST(dm_test_power_regulator_get, UT_TESTF_SCAN_FDT); + +/* Test regulator set and get Voltage method */ +static int dm_test_power_regulator_set_get_voltage(struct unit_test_state *uts) +{ + struct dm_regulator_uclass_plat *uc_pdata; + struct udevice *dev; + const char *platname; + int val_set, val_get; + + /* Set and get Voltage of BUCK1 - set to 'min' constraint */ + platname = regulator_names[BUCK1][PLATNAME]; + ut_assertok(regulator_get_by_platname(platname, &dev)); + + uc_pdata = dev_get_uclass_plat(dev); + ut_assert(uc_pdata); + + val_set = uc_pdata->min_uV; + ut_assertok(regulator_set_value(dev, val_set)); + + val_get = regulator_get_value(dev); + ut_assert(val_get >= 0); + + ut_asserteq(val_set, val_get); + + return 0; +} +DM_TEST(dm_test_power_regulator_set_get_voltage, UT_TESTF_SCAN_FDT); + +/* Test regulator set and get Current method */ +static int dm_test_power_regulator_set_get_current(struct unit_test_state *uts) +{ + struct dm_regulator_uclass_plat *uc_pdata; + struct udevice *dev; + const char *platname; + int val_set, val_get; + + /* Set and get the Current of LDO1 - set to 'min' constraint */ + platname = regulator_names[LDO1][PLATNAME]; + ut_assertok(regulator_get_by_platname(platname, &dev)); + + uc_pdata = dev_get_uclass_plat(dev); + ut_assert(uc_pdata); + + val_set = uc_pdata->min_uA; + ut_assertok(regulator_set_current(dev, val_set)); + + val_get = regulator_get_current(dev); + ut_assert(val_get >= 0); + + ut_asserteq(val_set, val_get); + + /* Check LDO2 current limit constraints - should be -ENODATA */ + platname = regulator_names[LDO2][PLATNAME]; + ut_assertok(regulator_get_by_platname(platname, &dev)); + + uc_pdata = dev_get_uclass_plat(dev); + ut_assert(uc_pdata); + ut_asserteq(-ENODATA, uc_pdata->min_uA); + ut_asserteq(-ENODATA, uc_pdata->max_uA); + + /* Try set the Current of LDO2 - should return -ENOSYS */ + ut_asserteq(-ENOSYS, regulator_set_current(dev, 0)); + + return 0; +} +DM_TEST(dm_test_power_regulator_set_get_current, UT_TESTF_SCAN_FDT); + +/* Test regulator set and get Enable method */ +static int dm_test_power_regulator_set_get_enable(struct unit_test_state *uts) +{ + const char *platname; + struct udevice *dev; + bool val_set = true; + + /* Set the Enable of LDO1 - default is disabled */ + platname = regulator_names[LDO1][PLATNAME]; + ut_assertok(regulator_get_by_platname(platname, &dev)); + ut_assertok(regulator_set_enable(dev, val_set)); + + /* Get the Enable state of LDO1 and compare it with the requested one */ + ut_asserteq(regulator_get_enable(dev), val_set); + + return 0; +} +DM_TEST(dm_test_power_regulator_set_get_enable, UT_TESTF_SCAN_FDT); + +/* Test regulator set and get enable if allowed method */ +static +int dm_test_power_regulator_set_enable_if_allowed(struct unit_test_state *uts) +{ + const char *platname; + struct udevice *dev, *dev_autoset; + bool val_set = false; + + /* Get BUCK1 - always on regulator */ + platname = regulator_names[BUCK1][PLATNAME]; + ut_assertok(regulator_autoset_by_name(platname, &dev_autoset)); + ut_assertok(regulator_get_by_platname(platname, &dev)); + + /* Try disabling always-on regulator */ + ut_assertok(regulator_set_enable_if_allowed(dev, val_set)); + ut_asserteq(regulator_get_enable(dev), !val_set); + + return 0; +} +DM_TEST(dm_test_power_regulator_set_enable_if_allowed, UT_TESTF_SCAN_FDT); + +/* Test regulator set and get mode method */ +static int dm_test_power_regulator_set_get_mode(struct unit_test_state *uts) +{ + const char *platname; + struct udevice *dev; + int val_set = LDO_OM_SLEEP; + + /* Set the mode id to LDO_OM_SLEEP of LDO1 - default is LDO_OM_OFF */ + platname = regulator_names[LDO1][PLATNAME]; + ut_assertok(regulator_get_by_platname(platname, &dev)); + ut_assertok(regulator_set_mode(dev, val_set)); + + /* Get the mode id of LDO1 and compare it with the requested one */ + ut_asserteq(regulator_get_mode(dev), val_set); + + return 0; +} +DM_TEST(dm_test_power_regulator_set_get_mode, UT_TESTF_SCAN_FDT); + +/* Test regulator set and get suspend Voltage method */ +static int dm_test_power_regulator_set_get_suspend_voltage(struct unit_test_state *uts) +{ + struct dm_regulator_uclass_plat *uc_pdata; + const struct dm_regulator_ops *ops; + struct udevice *dev; + const char *platname; + int val_set, val_get; + + /* Set and get Voltage of BUCK1 - set to 'min' constraint */ + platname = regulator_names[BUCK1][PLATNAME]; + ut_assertok(regulator_get_by_platname(platname, &dev)); + + uc_pdata = dev_get_uclass_plat(dev); + ut_assert(uc_pdata); + + ops = dev_get_driver_ops(dev); + + if (ops->set_suspend_value && ops->get_suspend_value) { + val_set = uc_pdata->suspend_uV; + ut_assertok(regulator_set_suspend_value(dev, val_set)); + val_get = regulator_get_suspend_value(dev); + ut_assert(val_get >= 0); + + ut_asserteq(val_set, val_get); + } + return 0; +} +DM_TEST(dm_test_power_regulator_set_get_suspend_voltage, UT_TESTF_SCAN_FDT); + +/* Test regulator set and get suspend Enable method */ +static int dm_test_power_regulator_set_get_suspend_enable(struct unit_test_state *uts) +{ + const struct dm_regulator_ops *ops; + const char *platname; + struct udevice *dev; + bool val_set = true; + + /* Set the Enable of LDO1 - default is disabled */ + platname = regulator_names[LDO1][PLATNAME]; + ut_assertok(regulator_get_by_platname(platname, &dev)); + + ops = dev_get_driver_ops(dev); + + if (ops->set_suspend_enable && ops->get_suspend_enable) { + ut_assertok(regulator_set_suspend_enable(dev, val_set)); + + /* + * Get the Enable state of LDO1 and + * compare it with the requested one + */ + ut_asserteq(regulator_get_suspend_enable(dev), val_set); + } + return 0; +} +DM_TEST(dm_test_power_regulator_set_get_suspend_enable, UT_TESTF_SCAN_FDT); + +/* Test regulator autoset method */ +static int dm_test_power_regulator_autoset(struct unit_test_state *uts) +{ + const char *platname; + struct udevice *dev, *dev_autoset; + + /* + * Test the BUCK1 with fdt properties + * - min-microvolt = max-microvolt = 1200000 + * - min-microamp = max-microamp = 200000 + * - always-on = set + * - boot-on = not set + * Expected output state: uV=1200000; uA=200000; output enabled + */ + platname = regulator_names[BUCK1][PLATNAME]; + ut_assertok(regulator_autoset_by_name(platname, &dev_autoset)); + + /* Check, that the returned device is proper */ + ut_assertok(regulator_get_by_platname(platname, &dev)); + ut_asserteq_ptr(dev, dev_autoset); + + /* Check the setup after autoset */ + ut_asserteq(regulator_get_value(dev), + SANDBOX_BUCK1_AUTOSET_EXPECTED_UV); + ut_asserteq(regulator_get_current(dev), + SANDBOX_BUCK1_AUTOSET_EXPECTED_UA); + ut_asserteq(regulator_get_enable(dev), + SANDBOX_BUCK1_AUTOSET_EXPECTED_ENABLE); + + return 0; +} +DM_TEST(dm_test_power_regulator_autoset, UT_TESTF_SCAN_FDT); + +/* + * Struct setting: to keep the expected output settings. + * @voltage: Voltage value [uV] + * @current: Current value [uA] + * @enable: output enable state: true/false + */ +struct setting { + int voltage; + int current; + bool enable; +}; + +/* + * platname_list: an array of regulator platform names. + * For testing regulator_list_autoset() for outputs: + * - LDO1 + * - LDO2 + */ +static const char *platname_list[] = { + SANDBOX_LDO1_PLATNAME, + SANDBOX_LDO2_PLATNAME, + NULL, +}; + +/* + * expected_setting_list: an array of regulator output setting, expected after + * call of the regulator_list_autoset() for the "platname_list" array. + * For testing results of regulator_list_autoset() for outputs: + * - LDO1 + * - LDO2 + * The settings are defined in: include/power/sandbox_pmic.h + */ +static const struct setting expected_setting_list[] = { + [0] = { /* LDO1 */ + .voltage = SANDBOX_LDO1_AUTOSET_EXPECTED_UV, + .current = SANDBOX_LDO1_AUTOSET_EXPECTED_UA, + .enable = SANDBOX_LDO1_AUTOSET_EXPECTED_ENABLE, + }, + [1] = { /* LDO2 */ + .voltage = SANDBOX_LDO2_AUTOSET_EXPECTED_UV, + .current = SANDBOX_LDO2_AUTOSET_EXPECTED_UA, + .enable = SANDBOX_LDO2_AUTOSET_EXPECTED_ENABLE, + }, +}; + +static int list_count = ARRAY_SIZE(expected_setting_list); + +/* Test regulator list autoset method */ +static int dm_test_power_regulator_autoset_list(struct unit_test_state *uts) +{ + struct udevice *dev_list[2], *dev; + int i; + + /* + * Test the settings of the regulator list: + * LDO1 with fdt properties: + * - min-microvolt = max-microvolt = 1800000 + * - min-microamp = max-microamp = 100000 + * - always-on = not set + * - boot-on = set + * Expected output state: uV=1800000; uA=100000; output enabled + * + * LDO2 with fdt properties: + * - min-microvolt = max-microvolt = 3300000 + * - always-on = not set + * - boot-on = not set + * Expected output state: uV=300000(default); output disabled(default) + * The expected settings are defined in: include/power/sandbox_pmic.h. + */ + ut_assertok(regulator_list_autoset(platname_list, dev_list, false)); + + for (i = 0; i < list_count; i++) { + /* Check, that the returned device is non-NULL */ + ut_assert(dev_list[i]); + + /* Check, that the returned device is proper */ + ut_assertok(regulator_get_by_platname(platname_list[i], &dev)); + ut_asserteq_ptr(dev_list[i], dev); + + /* Check, that regulator output Voltage value is as expected */ + ut_asserteq(regulator_get_value(dev_list[i]), + expected_setting_list[i].voltage); + + /* Check, that regulator output Current value is as expected */ + ut_asserteq(regulator_get_current(dev_list[i]), + expected_setting_list[i].current); + + /* Check, that regulator output Enable state is as expected */ + ut_asserteq(regulator_get_enable(dev_list[i]), + expected_setting_list[i].enable); + } + + return 0; +} +DM_TEST(dm_test_power_regulator_autoset_list, UT_TESTF_SCAN_FDT); diff --git a/roms/u-boot/test/dm/remoteproc.c b/roms/u-boot/test/dm/remoteproc.c new file mode 100644 index 000000000..1cc07bc80 --- /dev/null +++ b/roms/u-boot/test/dm/remoteproc.c @@ -0,0 +1,259 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * (C) Copyright 2015 + * Texas Instruments Incorporated - http://www.ti.com/ + */ +#include <common.h> +#include <dm.h> +#include <elf.h> +#include <errno.h> +#include <remoteproc.h> +#include <asm/io.h> +#include <dm/test.h> +#include <test/test.h> +#include <test/ut.h> + +/** + * dm_test_remoteproc_base() - test the operations after initializations + * @uts: unit test state + * + * Return: 0 if test passed, else error + */ +static int dm_test_remoteproc_base(struct unit_test_state *uts) +{ + if (!rproc_is_initialized()) + ut_assertok(rproc_init()); + + /* Ensure we are initialized */ + ut_asserteq(true, rproc_is_initialized()); + + + /* platform data device 1 */ + ut_assertok(rproc_stop(0)); + ut_assertok(rproc_reset(0)); + /* -> invalid attempt tests */ + ut_asserteq(-EINVAL, rproc_start(0)); + ut_asserteq(-EINVAL, rproc_ping(0)); + /* Valid tests */ + ut_assertok(rproc_load(0, 1, 0)); + ut_assertok(rproc_start(0)); + ut_assertok(rproc_is_running(0)); + ut_assertok(rproc_ping(0)); + ut_assertok(rproc_reset(0)); + ut_assertok(rproc_stop(0)); + + /* dt device device 1 */ + ut_assertok(rproc_stop(1)); + ut_assertok(rproc_reset(1)); + ut_assertok(rproc_load(1, 1, 0)); + ut_assertok(rproc_start(1)); + ut_assertok(rproc_is_running(1)); + ut_assertok(rproc_ping(1)); + ut_assertok(rproc_reset(1)); + ut_assertok(rproc_stop(1)); + + /* dt device device 2 */ + ut_assertok(rproc_stop(0)); + ut_assertok(rproc_reset(0)); + /* -> invalid attempt tests */ + ut_asserteq(-EINVAL, rproc_start(0)); + ut_asserteq(-EINVAL, rproc_ping(0)); + /* Valid tests */ + ut_assertok(rproc_load(2, 1, 0)); + ut_assertok(rproc_start(2)); + ut_assertok(rproc_is_running(2)); + ut_assertok(rproc_ping(2)); + ut_assertok(rproc_reset(2)); + ut_assertok(rproc_stop(2)); + + return 0; +} +DM_TEST(dm_test_remoteproc_base, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); + +#define DEVICE_TO_PHYSICAL_OFFSET 0x1000 +/** + * dm_test_remoteproc_elf() - test the ELF operations + * @uts: unit test state + * + * Return: 0 if test passed, else error + */ +static int dm_test_remoteproc_elf(struct unit_test_state *uts) +{ + u8 valid_elf32[] = { + /* @0x00 - ELF HEADER - */ + /* ELF magic */ + 0x7f, 0x45, 0x4c, 0x46, + /* 32 Bits */ + 0x01, + /* Endianness */ +#ifdef __LITTLE_ENDIAN + 0x01, +#else + 0x02, +#endif + /* Version */ + 0x01, + /* Padding */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* Type : executable */ + 0x02, 0x00, + /* Machine: ARM */ + 0x28, 0x00, + /* Version */ + 0x01, 0x00, 0x00, 0x00, + /* Entry */ + 0x00, 0x00, 0x00, 0x08, + /* phoff (program header offset @ 0x40)*/ + 0x40, 0x00, 0x00, 0x00, + /* shoff (section header offset @ 0x90) */ + 0x90, 0x00, 0x00, 0x00, + /* flags */ + 0x00, 0x00, 0x00, 0x00, + /* ehsize (elf header size = 0x34) */ + 0x34, 0x00, + /* phentsize (program header size = 0x20) */ + 0x20, 0x00, + /* phnum (program header number : 1) */ + 0x01, 0x00, + /* shentsize (section header size : 40 bytes) */ + 0x28, 0x00, + /* shnum (section header number: 3) */ + 0x02, 0x00, + /* shstrndx (section header name section index: 1) */ + 0x01, 0x00, + /* padding */ + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + + /* @0x40 - PROGRAM HEADER TABLE - */ + /* type : PT_LOAD */ + 0x01, 0x00, 0x00, 0x00, + /* offset */ + 0x00, 0x00, 0x00, 0x00, + /* vaddr */ + 0x00, 0x00, 0x00, 0x00, + /* paddr : physical address */ + 0x00, 0x00, 0x00, 0x00, + /* filesz : 0x20 bytes (program header size) */ + 0x20, 0x00, 0x00, 0x00, + /* memsz = filesz */ + 0x20, 0x00, 0x00, 0x00, + /* flags : readable and exectuable */ + 0x05, 0x00, 0x00, 0x00, + /* padding */ + 0x00, 0x00, 0x00, 0x00, + + /* @0x60 - RESOURCE TABLE SECTION - */ + /* version */ + 0x01, 0x00, 0x00, 0x00, + /* num (0, no entries) */ + 0x00, 0x00, 0x00, 0x00, + /* Reserved */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + + /* @0x70 - SECTION'S NAMES SECTION - */ + /* section 0 name (".shrtrtab") */ + 0x2e, 0x73, 0x68, 0x73, 0x74, 0x72, 0x74, 0x61, 0x62, 0x00, + /* section 1 name (".resource_table") */ + 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, + 0x74, 0x61, 0x62, 0x6c, 0x65, 0x00, + /* padding */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + + /* @0x90 - SECTION HEADER TABLE - */ + /* Section 0 : resource table header */ + /* sh_name - index into section header string table section */ + 0x0a, 0x00, 0x00, 0x00, + /* sh_type and sh_flags */ + 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + /* sh_addr = where the resource table has to be copied to */ + 0x00, 0x00, 0x00, 0x00, + /* sh_offset = 0x60 */ + 0x60, 0x00, 0x00, 0x00, + /* sh_size = 16 bytes */ + 0x10, 0x00, 0x00, 0x00, + /* sh_link, sh_info, sh_addralign, sh_entsize */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* Section 1 : section's names section header */ + /* sh_name - index into section header string table section */ + 0x00, 0x00, 0x00, 0x00, + /* sh_type and sh_flags */ + 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* sh_addr */ + 0x00, 0x00, 0x00, 0x00, + /* sh_offset = 0x70 */ + 0x70, 0x00, 0x00, 0x00, + /* sh_size = 27 bytes */ + 0x1b, 0x00, 0x00, 0x00, + /* sh_link, sh_info, sh_addralign, sh_entsize */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + }; + unsigned int size = ARRAY_SIZE(valid_elf32); + struct udevice *dev; + phys_addr_t loaded_firmware_paddr, loaded_rsc_table_paddr; + void *loaded_firmware, *loaded_rsc_table; + u32 loaded_firmware_size, rsc_table_size; + ulong rsc_addr, rsc_size; + Elf32_Ehdr *ehdr = (Elf32_Ehdr *)valid_elf32; + Elf32_Phdr *phdr = (Elf32_Phdr *)(valid_elf32 + ehdr->e_phoff); + Elf32_Shdr *shdr = (Elf32_Shdr *)(valid_elf32 + ehdr->e_shoff); + + ut_assertok(uclass_get_device(UCLASS_REMOTEPROC, 0, &dev)); + + /* + * In its Program Header Table, let the firmware specifies to be loaded + * at SDRAM_BASE *device* address (p_paddr field). + * Its size is defined by the p_filesz field. + */ + phdr->p_paddr = CONFIG_SYS_SDRAM_BASE; + loaded_firmware_size = phdr->p_filesz; + + /* + * This *device* address is converted to a *physical* address by the + * device_to_virt() operation of sandbox_test_rproc which returns + * DeviceAddress + DEVICE_TO_PHYSICAL_OFFSET. + * This is where we expect to get the firmware loaded. + */ + loaded_firmware_paddr = phdr->p_paddr + DEVICE_TO_PHYSICAL_OFFSET; + loaded_firmware = map_physmem(loaded_firmware_paddr, + loaded_firmware_size, MAP_NOCACHE); + ut_assertnonnull(loaded_firmware); + memset(loaded_firmware, 0, loaded_firmware_size); + + /* Load firmware in loaded_firmware, and verify it */ + ut_assertok(rproc_elf32_load_image(dev, (ulong)valid_elf32, size)); + ut_asserteq_mem(loaded_firmware, valid_elf32, loaded_firmware_size); + ut_asserteq(rproc_elf_get_boot_addr(dev, (unsigned long)valid_elf32), + 0x08000000); + unmap_physmem(loaded_firmware, MAP_NOCACHE); + + /* Resource table */ + shdr->sh_addr = CONFIG_SYS_SDRAM_BASE; + rsc_table_size = shdr->sh_size; + + loaded_rsc_table_paddr = shdr->sh_addr + DEVICE_TO_PHYSICAL_OFFSET; + loaded_rsc_table = map_physmem(loaded_rsc_table_paddr, + rsc_table_size, MAP_NOCACHE); + ut_assertnonnull(loaded_rsc_table); + memset(loaded_rsc_table, 0, rsc_table_size); + + /* Load and verify */ + ut_assertok(rproc_elf32_load_rsc_table(dev, (ulong)valid_elf32, size, + &rsc_addr, &rsc_size)); + ut_asserteq(rsc_addr, CONFIG_SYS_SDRAM_BASE); + ut_asserteq(rsc_size, rsc_table_size); + ut_asserteq_mem(loaded_firmware, valid_elf32 + shdr->sh_offset, + shdr->sh_size); + unmap_physmem(loaded_firmware, MAP_NOCACHE); + + /* Invalid ELF Magic */ + valid_elf32[0] = 0; + ut_asserteq(-EPROTONOSUPPORT, + rproc_elf32_sanity_check((ulong)valid_elf32, size)); + + return 0; +} +DM_TEST(dm_test_remoteproc_elf, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); diff --git a/roms/u-boot/test/dm/reset.c b/roms/u-boot/test/dm/reset.c new file mode 100644 index 000000000..9c0045233 --- /dev/null +++ b/roms/u-boot/test/dm/reset.c @@ -0,0 +1,186 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2016, NVIDIA CORPORATION. + */ + +#include <common.h> +#include <dm.h> +#include <dm/device-internal.h> +#include <log.h> +#include <malloc.h> +#include <reset.h> +#include <dm/test.h> +#include <asm/reset.h> +#include <test/test.h> +#include <test/ut.h> + +/* This must match the specifier for mbox-names="test" in the DT node */ +#define TEST_RESET_ID 2 + +/* This is the other reset phandle specifier handled by bulk */ +#define OTHER_RESET_ID 2 + +/* Base test of the reset uclass */ +static int dm_test_reset_base(struct unit_test_state *uts) +{ + struct udevice *dev; + struct reset_ctl reset_method1, reset_method1_1; + struct reset_ctl reset_method2, reset_method2_1; + struct reset_ctl reset_method3, reset_method3_1; + struct reset_ctl reset_method4, reset_method4_1; + + /* Get the device using the reset device */ + ut_assertok(uclass_get_device_by_name(UCLASS_MISC, "reset-ctl-test", + &dev)); + + /* Get the same reset port in 2 different ways and compare */ + ut_assertok(reset_get_by_index(dev, 0, &reset_method1)); + ut_assertok(reset_get_by_index_nodev(dev_ofnode(dev), 0, + &reset_method1_1)); + ut_assertok(reset_get_by_index(dev, 1, &reset_method2)); + ut_assertok(reset_get_by_index_nodev(dev_ofnode(dev), 1, + &reset_method2_1)); + ut_assertok(reset_get_by_index(dev, 2, &reset_method3)); + ut_assertok(reset_get_by_index_nodev(dev_ofnode(dev), 2, + &reset_method3_1)); + ut_assertok(reset_get_by_index(dev, 3, &reset_method4)); + ut_assertok(reset_get_by_index_nodev(dev_ofnode(dev), 3, + &reset_method4_1)); + + ut_asserteq(reset_method1.id, reset_method1_1.id); + ut_asserteq(reset_method2.id, reset_method2_1.id); + ut_asserteq(reset_method3.id, reset_method3_1.id); + ut_asserteq(reset_method4.id, reset_method4_1.id); + + ut_asserteq(true, reset_method1.id != reset_method2.id); + ut_asserteq(true, reset_method1.id != reset_method3.id); + ut_asserteq(true, reset_method1.id != reset_method4.id); + ut_asserteq(true, reset_method2.id != reset_method3.id); + ut_asserteq(true, reset_method2.id != reset_method4.id); + ut_asserteq(true, reset_method3.id != reset_method4.id); + + ut_asserteq(true, reset_method1_1.id != reset_method2_1.id); + ut_asserteq(true, reset_method1_1.id != reset_method3_1.id); + ut_asserteq(true, reset_method1_1.id != reset_method4_1.id); + ut_asserteq(true, reset_method2_1.id != reset_method3_1.id); + ut_asserteq(true, reset_method2_1.id != reset_method4_1.id); + ut_asserteq(true, reset_method3_1.id != reset_method4_1.id); + + return 0; +} + +DM_TEST(dm_test_reset_base, UT_TESTF_SCAN_FDT); + +static int dm_test_reset(struct unit_test_state *uts) +{ + struct udevice *dev_reset; + struct udevice *dev_test; + + ut_assertok(uclass_get_device_by_name(UCLASS_RESET, "reset-ctl", + &dev_reset)); + ut_asserteq(0, sandbox_reset_query(dev_reset, TEST_RESET_ID)); + + ut_assertok(uclass_get_device_by_name(UCLASS_MISC, "reset-ctl-test", + &dev_test)); + ut_assertok(sandbox_reset_test_get(dev_test)); + + ut_assertok(sandbox_reset_test_assert(dev_test)); + ut_asserteq(1, sandbox_reset_query(dev_reset, TEST_RESET_ID)); + + ut_assertok(sandbox_reset_test_deassert(dev_test)); + ut_asserteq(0, sandbox_reset_query(dev_reset, TEST_RESET_ID)); + + ut_asserteq(1, sandbox_reset_is_requested(dev_reset, TEST_RESET_ID)); + ut_assertok(sandbox_reset_test_free(dev_test)); + ut_asserteq(0, sandbox_reset_is_requested(dev_reset, TEST_RESET_ID)); + + return 0; +} +DM_TEST(dm_test_reset, UT_TESTF_SCAN_FDT); + +static int dm_test_reset_devm(struct unit_test_state *uts) +{ + struct udevice *dev_reset; + struct udevice *dev_test; + + ut_assertok(uclass_get_device_by_name(UCLASS_RESET, "reset-ctl", + &dev_reset)); + ut_asserteq(0, sandbox_reset_query(dev_reset, TEST_RESET_ID)); + ut_assertok(uclass_get_device_by_name(UCLASS_MISC, "reset-ctl-test", + &dev_test)); + ut_assertok(sandbox_reset_test_get_devm(dev_test)); + + ut_assertok(sandbox_reset_test_assert(dev_test)); + ut_asserteq(1, sandbox_reset_query(dev_reset, TEST_RESET_ID)); + ut_assertok(sandbox_reset_test_deassert(dev_test)); + ut_asserteq(0, sandbox_reset_query(dev_reset, TEST_RESET_ID)); + + ut_asserteq(1, sandbox_reset_is_requested(dev_reset, TEST_RESET_ID)); + ut_assertok(device_remove(dev_test, DM_REMOVE_NORMAL)); + ut_asserteq(0, sandbox_reset_is_requested(dev_reset, TEST_RESET_ID)); + + return 0; +} +DM_TEST(dm_test_reset_devm, UT_TESTF_SCAN_FDT); + +static int dm_test_reset_bulk(struct unit_test_state *uts) +{ + struct udevice *dev_reset; + struct udevice *dev_test; + + ut_assertok(uclass_get_device_by_name(UCLASS_RESET, "reset-ctl", + &dev_reset)); + ut_asserteq(0, sandbox_reset_query(dev_reset, TEST_RESET_ID)); + ut_asserteq(0, sandbox_reset_query(dev_reset, OTHER_RESET_ID)); + + ut_assertok(uclass_get_device_by_name(UCLASS_MISC, "reset-ctl-test", + &dev_test)); + ut_assertok(sandbox_reset_test_get_bulk(dev_test)); + + ut_assertok(sandbox_reset_test_assert_bulk(dev_test)); + ut_asserteq(1, sandbox_reset_query(dev_reset, TEST_RESET_ID)); + ut_asserteq(1, sandbox_reset_query(dev_reset, OTHER_RESET_ID)); + + ut_assertok(sandbox_reset_test_deassert_bulk(dev_test)); + ut_asserteq(0, sandbox_reset_query(dev_reset, TEST_RESET_ID)); + ut_asserteq(0, sandbox_reset_query(dev_reset, OTHER_RESET_ID)); + + ut_assertok(sandbox_reset_test_release_bulk(dev_test)); + ut_asserteq(1, sandbox_reset_query(dev_reset, TEST_RESET_ID)); + ut_asserteq(1, sandbox_reset_query(dev_reset, OTHER_RESET_ID)); + + return 0; +} +DM_TEST(dm_test_reset_bulk, UT_TESTF_SCAN_FDT); + +static int dm_test_reset_bulk_devm(struct unit_test_state *uts) +{ + struct udevice *dev_reset; + struct udevice *dev_test; + + ut_assertok(uclass_get_device_by_name(UCLASS_RESET, "reset-ctl", + &dev_reset)); + ut_asserteq(0, sandbox_reset_query(dev_reset, TEST_RESET_ID)); + ut_asserteq(0, sandbox_reset_query(dev_reset, OTHER_RESET_ID)); + + ut_assertok(uclass_get_device_by_name(UCLASS_MISC, "reset-ctl-test", + &dev_test)); + ut_assertok(sandbox_reset_test_get_bulk_devm(dev_test)); + + ut_assertok(sandbox_reset_test_assert_bulk(dev_test)); + ut_asserteq(1, sandbox_reset_query(dev_reset, TEST_RESET_ID)); + ut_asserteq(1, sandbox_reset_query(dev_reset, OTHER_RESET_ID)); + + ut_assertok(sandbox_reset_test_deassert_bulk(dev_test)); + ut_asserteq(0, sandbox_reset_query(dev_reset, TEST_RESET_ID)); + ut_asserteq(0, sandbox_reset_query(dev_reset, OTHER_RESET_ID)); + + ut_asserteq(1, sandbox_reset_is_requested(dev_reset, OTHER_RESET_ID)); + ut_asserteq(1, sandbox_reset_is_requested(dev_reset, TEST_RESET_ID)); + ut_assertok(device_remove(dev_test, DM_REMOVE_NORMAL)); + ut_asserteq(0, sandbox_reset_is_requested(dev_reset, TEST_RESET_ID)); + ut_asserteq(0, sandbox_reset_is_requested(dev_reset, OTHER_RESET_ID)); + + return 0; +} +DM_TEST(dm_test_reset_bulk_devm, UT_TESTF_SCAN_FDT); diff --git a/roms/u-boot/test/dm/rng.c b/roms/u-boot/test/dm/rng.c new file mode 100644 index 000000000..5b34c93ed --- /dev/null +++ b/roms/u-boot/test/dm/rng.c @@ -0,0 +1,27 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (c) 2019, Linaro Limited + */ + +#include <common.h> +#include <dm.h> +#include <log.h> +#include <rng.h> +#include <dm/test.h> +#include <test/ut.h> + +/* Basic test of the rng uclass */ +static int dm_test_rng_read(struct unit_test_state *uts) +{ + unsigned long rand1 = 0, rand2 = 0; + struct udevice *dev; + + ut_assertok(uclass_get_device(UCLASS_RNG, 0, &dev)); + ut_assertnonnull(dev); + ut_assertok(dm_rng_read(dev, &rand1, sizeof(rand1))); + ut_assertok(dm_rng_read(dev, &rand2, sizeof(rand2))); + ut_assert(rand1 != rand2); + + return 0; +} +DM_TEST(dm_test_rng_read, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); diff --git a/roms/u-boot/test/dm/rtc.c b/roms/u-boot/test/dm/rtc.c new file mode 100644 index 000000000..8ab997c87 --- /dev/null +++ b/roms/u-boot/test/dm/rtc.c @@ -0,0 +1,293 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2015 Google, Inc + * Written by Simon Glass <sjg@chromium.org> + */ + +#include <common.h> +#include <console.h> +#include <dm.h> +#include <i2c.h> +#include <log.h> +#include <rtc.h> +#include <asm/io.h> +#include <asm/rtc.h> +#include <asm/test.h> +#include <dm/test.h> +#include <test/test.h> +#include <test/ut.h> + +/* Simple RTC sanity check */ +static int dm_test_rtc_base(struct unit_test_state *uts) +{ + struct udevice *dev; + + ut_asserteq(-ENODEV, uclass_get_device_by_seq(UCLASS_RTC, 2, &dev)); + ut_assertok(uclass_get_device(UCLASS_RTC, 0, &dev)); + ut_assertok(uclass_get_device(UCLASS_RTC, 1, &dev)); + + return 0; +} +DM_TEST(dm_test_rtc_base, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); + +static void show_time(const char *msg, struct rtc_time *time) +{ + printf("%s: %02d/%02d/%04d %02d:%02d:%02d\n", msg, + time->tm_mday, time->tm_mon, time->tm_year, + time->tm_hour, time->tm_min, time->tm_sec); +} + +static int cmp_times(struct rtc_time *expect, struct rtc_time *time, bool show) +{ + bool same; + + same = expect->tm_sec == time->tm_sec; + same &= expect->tm_min == time->tm_min; + same &= expect->tm_hour == time->tm_hour; + same &= expect->tm_mday == time->tm_mday; + same &= expect->tm_mon == time->tm_mon; + same &= expect->tm_year == time->tm_year; + if (!same && show) { + show_time("expected", expect); + show_time("actual", time); + } + + return same ? 0 : -EINVAL; +} + +/* Set and get the time */ +static int dm_test_rtc_set_get(struct unit_test_state *uts) +{ + struct rtc_time now, time, cmp; + struct udevice *dev, *emul; + long offset, old_offset, old_base_time; + + ut_assertok(uclass_get_device(UCLASS_RTC, 0, &dev)); + ut_assertok(dm_rtc_get(dev, &now)); + + ut_assertok(i2c_emul_find(dev, &emul)); + ut_assert(emul != NULL); + + /* Tell the RTC to go into manual mode */ + old_offset = sandbox_i2c_rtc_set_offset(emul, false, 0); + old_base_time = sandbox_i2c_rtc_get_set_base_time(emul, -1); + + memset(&time, '\0', sizeof(time)); + time.tm_mday = 3; + time.tm_mon = 6; + time.tm_year = 2004; + time.tm_sec = 0; + time.tm_min = 18; + time.tm_hour = 18; + ut_assertok(dm_rtc_set(dev, &time)); + + memset(&cmp, '\0', sizeof(cmp)); + ut_assertok(dm_rtc_get(dev, &cmp)); + ut_assertok(cmp_times(&time, &cmp, true)); + + memset(&time, '\0', sizeof(time)); + time.tm_mday = 31; + time.tm_mon = 8; + time.tm_year = 2004; + time.tm_sec = 0; + time.tm_min = 18; + time.tm_hour = 18; + ut_assertok(dm_rtc_set(dev, &time)); + + memset(&cmp, '\0', sizeof(cmp)); + ut_assertok(dm_rtc_get(dev, &cmp)); + ut_assertok(cmp_times(&time, &cmp, true)); + + /* Increment by 1 second */ + offset = sandbox_i2c_rtc_set_offset(emul, false, 0); + sandbox_i2c_rtc_set_offset(emul, false, offset + 1); + + memset(&cmp, '\0', sizeof(cmp)); + ut_assertok(dm_rtc_get(dev, &cmp)); + ut_asserteq(1, cmp.tm_sec); + + /* Check against original offset */ + sandbox_i2c_rtc_set_offset(emul, false, old_offset); + ut_assertok(dm_rtc_get(dev, &cmp)); + ut_assertok(cmp_times(&now, &cmp, true)); + + /* Back to the original offset */ + sandbox_i2c_rtc_set_offset(emul, false, 0); + memset(&cmp, '\0', sizeof(cmp)); + ut_assertok(dm_rtc_get(dev, &cmp)); + ut_assertok(cmp_times(&now, &cmp, true)); + + /* Increment the base time by 1 emul */ + sandbox_i2c_rtc_get_set_base_time(emul, old_base_time + 1); + memset(&cmp, '\0', sizeof(cmp)); + ut_assertok(dm_rtc_get(dev, &cmp)); + if (now.tm_sec == 59) { + ut_asserteq(0, cmp.tm_sec); + } else { + ut_asserteq(now.tm_sec + 1, cmp.tm_sec); + } + + old_offset = sandbox_i2c_rtc_set_offset(emul, true, 0); + + return 0; +} +DM_TEST(dm_test_rtc_set_get, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); + +static int dm_test_rtc_read_write(struct unit_test_state *uts) +{ + struct rtc_time time; + struct udevice *dev, *emul; + long old_offset; + u8 buf[4], reg; + + ut_assertok(uclass_get_device(UCLASS_RTC, 0, &dev)); + + memcpy(buf, "car", 4); + ut_assertok(dm_rtc_write(dev, REG_AUX0, buf, 4)); + memset(buf, '\0', sizeof(buf)); + ut_assertok(dm_rtc_read(dev, REG_AUX0, buf, 4)); + ut_asserteq(memcmp(buf, "car", 4), 0); + + reg = 'b'; + ut_assertok(dm_rtc_write(dev, REG_AUX0, ®, 1)); + memset(buf, '\0', sizeof(buf)); + ut_assertok(dm_rtc_read(dev, REG_AUX0, buf, 4)); + ut_asserteq(memcmp(buf, "bar", 4), 0); + + reg = 't'; + ut_assertok(dm_rtc_write(dev, REG_AUX2, ®, 1)); + memset(buf, '\0', sizeof(buf)); + ut_assertok(dm_rtc_read(dev, REG_AUX1, buf, 3)); + ut_asserteq(memcmp(buf, "at", 3), 0); + + ut_assertok(i2c_emul_find(dev, &emul)); + ut_assert(emul != NULL); + + old_offset = sandbox_i2c_rtc_set_offset(emul, false, 0); + ut_assertok(dm_rtc_get(dev, &time)); + + ut_assertok(dm_rtc_read(dev, REG_SEC, ®, 1)); + ut_asserteq(time.tm_sec, reg); + ut_assertok(dm_rtc_read(dev, REG_MDAY, ®, 1)); + ut_asserteq(time.tm_mday, reg); + + sandbox_i2c_rtc_set_offset(emul, true, old_offset); + + return 0; +} +DM_TEST(dm_test_rtc_read_write, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); + +/* Test 'rtc list' command */ +static int dm_test_rtc_cmd_list(struct unit_test_state *uts) +{ + console_record_reset(); + + run_command("rtc list", 0); + ut_assert_nextline("RTC #0 - rtc@43"); + ut_assert_nextline("RTC #1 - rtc@61"); + ut_assert_console_end(); + + return 0; +} +DM_TEST(dm_test_rtc_cmd_list, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); + +/* Test 'rtc read' and 'rtc write' commands */ +static int dm_test_rtc_cmd_rw(struct unit_test_state *uts) +{ + console_record_reset(); + + run_command("rtc dev 0", 0); + ut_assert_nextline("RTC #0 - rtc@43"); + ut_assert_console_end(); + + run_command("rtc write 0x30 aabb", 0); + ut_assert_console_end(); + + run_command("rtc read 0x30 2", 0); + ut_assert_nextline("00000030: aa bb .."); + ut_assert_console_end(); + + run_command("rtc dev 1", 0); + ut_assert_nextline("RTC #1 - rtc@61"); + ut_assert_console_end(); + + run_command("rtc write 0x30 ccdd", 0); + ut_assert_console_end(); + + run_command("rtc read 0x30 2", 0); + ut_assert_nextline("00000030: cc dd .."); + ut_assert_console_end(); + + /* + * Switch back to device #0, check that its aux registers + * still have the same values. + */ + run_command("rtc dev 0", 0); + ut_assert_nextline("RTC #0 - rtc@43"); + ut_assert_console_end(); + + run_command("rtc read 0x30 2", 0); + ut_assert_nextline("00000030: aa bb .."); + ut_assert_console_end(); + + return 0; +} +DM_TEST(dm_test_rtc_cmd_rw, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); + +/* Reset the time */ +static int dm_test_rtc_reset(struct unit_test_state *uts) +{ + struct rtc_time now; + struct udevice *dev, *emul; + long old_base_time, base_time; + + ut_assertok(uclass_get_device(UCLASS_RTC, 0, &dev)); + ut_assertok(dm_rtc_get(dev, &now)); + + ut_assertok(i2c_emul_find(dev, &emul)); + ut_assert(emul != NULL); + + old_base_time = sandbox_i2c_rtc_get_set_base_time(emul, 0); + + ut_asserteq(0, sandbox_i2c_rtc_get_set_base_time(emul, -1)); + + /* Resetting the RTC should put he base time back to normal */ + ut_assertok(dm_rtc_reset(dev)); + base_time = sandbox_i2c_rtc_get_set_base_time(emul, -1); + ut_asserteq(old_base_time, base_time); + + return 0; +} +DM_TEST(dm_test_rtc_reset, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); + +/* Check that two RTC devices can be used independently */ +static int dm_test_rtc_dual(struct unit_test_state *uts) +{ + struct rtc_time now1, now2, cmp; + struct udevice *dev1, *dev2; + struct udevice *emul1, *emul2; + long offset; + + ut_assertok(uclass_get_device(UCLASS_RTC, 0, &dev1)); + ut_assertok(dm_rtc_get(dev1, &now1)); + ut_assertok(uclass_get_device(UCLASS_RTC, 1, &dev2)); + ut_assertok(dm_rtc_get(dev2, &now2)); + + ut_assertok(i2c_emul_find(dev1, &emul1)); + ut_assert(emul1 != NULL); + ut_assertok(i2c_emul_find(dev2, &emul2)); + ut_assert(emul2 != NULL); + + offset = sandbox_i2c_rtc_set_offset(emul1, false, -1); + sandbox_i2c_rtc_set_offset(emul2, false, offset + 1); + memset(&cmp, '\0', sizeof(cmp)); + ut_assertok(dm_rtc_get(dev2, &cmp)); + ut_asserteq(-EINVAL, cmp_times(&now1, &cmp, false)); + + memset(&cmp, '\0', sizeof(cmp)); + ut_assertok(dm_rtc_get(dev1, &cmp)); + ut_assertok(cmp_times(&now1, &cmp, true)); + + return 0; +} +DM_TEST(dm_test_rtc_dual, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); diff --git a/roms/u-boot/test/dm/scmi.c b/roms/u-boot/test/dm/scmi.c new file mode 100644 index 000000000..c938e6d4f --- /dev/null +++ b/roms/u-boot/test/dm/scmi.c @@ -0,0 +1,260 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2020, Linaro Limited + * + * Tests scmi_agent uclass and the SCMI drivers implemented in other + * uclass devices probe when a SCMI server exposes resources. + * + * Note in test.dts the protocol@10 node in agent 1. Protocol 0x10 is not + * implemented in U-Boot SCMI components but the implementation is exepected + * to not complain on unknown protocol IDs, as long as it is not used. Note + * in test.dts tests that SCMI drivers probing does not fail for such an + * unknown SCMI protocol ID. + */ + +#include <common.h> +#include <clk.h> +#include <dm.h> +#include <reset.h> +#include <asm/scmi_test.h> +#include <dm/device-internal.h> +#include <dm/test.h> +#include <linux/kconfig.h> +#include <power/regulator.h> +#include <test/ut.h> + +static int ut_assert_scmi_state_preprobe(struct unit_test_state *uts) +{ + struct sandbox_scmi_service *scmi_ctx = sandbox_scmi_service_ctx(); + + ut_assertnonnull(scmi_ctx); + if (scmi_ctx->agent_count) + ut_asserteq(2, scmi_ctx->agent_count); + + return 0; +} + +static int ut_assert_scmi_state_postprobe(struct unit_test_state *uts, + struct udevice *dev) +{ + struct sandbox_scmi_devices *scmi_devices; + struct sandbox_scmi_service *scmi_ctx; + struct sandbox_scmi_agent *agent0; + struct sandbox_scmi_agent *agent1; + + /* Device references to check context against test sequence */ + scmi_devices = sandbox_scmi_devices_ctx(dev); + + ut_assertnonnull(scmi_devices); + ut_asserteq(3, scmi_devices->clk_count); + ut_asserteq(1, scmi_devices->reset_count); + ut_asserteq(2, scmi_devices->regul_count); + + /* State of the simulated SCMI server exposed */ + scmi_ctx = sandbox_scmi_service_ctx(); + agent0 = scmi_ctx->agent[0]; + agent1 = scmi_ctx->agent[1]; + + ut_asserteq(2, scmi_ctx->agent_count); + + ut_assertnonnull(agent0); + ut_asserteq(2, agent0->clk_count); + ut_assertnonnull(agent0->clk); + ut_asserteq(1, agent0->reset_count); + ut_assertnonnull(agent0->reset); + ut_asserteq(2, agent0->voltd_count); + ut_assertnonnull(agent0->voltd); + + ut_assertnonnull(agent1); + ut_assertnonnull(agent1->clk); + ut_asserteq(1, agent1->clk_count); + + return 0; +} + +static int load_sandbox_scmi_test_devices(struct unit_test_state *uts, + struct udevice **dev) +{ + int ret; + + ret = ut_assert_scmi_state_preprobe(uts); + if (ret) + return ret; + + ut_assertok(uclass_get_device_by_name(UCLASS_MISC, "sandbox_scmi", + dev)); + ut_assertnonnull(*dev); + + return ut_assert_scmi_state_postprobe(uts, *dev); +} + +static int release_sandbox_scmi_test_devices(struct unit_test_state *uts, + struct udevice *dev) +{ + ut_assertok(device_remove(dev, DM_REMOVE_NORMAL)); + + /* Not sure test devices are fully removed, agent may not be visible */ + return 0; +} + +/* + * Test SCMI states when loading and releasing resources + * related to SCMI drivers. + */ +static int dm_test_scmi_sandbox_agent(struct unit_test_state *uts) +{ + struct udevice *dev = NULL; + int ret; + + ret = load_sandbox_scmi_test_devices(uts, &dev); + if (!ret) + ret = release_sandbox_scmi_test_devices(uts, dev); + + return ret; +} +DM_TEST(dm_test_scmi_sandbox_agent, UT_TESTF_SCAN_FDT); + +static int dm_test_scmi_clocks(struct unit_test_state *uts) +{ + struct sandbox_scmi_devices *scmi_devices; + struct sandbox_scmi_service *scmi_ctx; + struct sandbox_scmi_agent *agent0; + struct sandbox_scmi_agent *agent1; + struct udevice *dev = NULL; + int ret_dev; + int ret; + + ret = load_sandbox_scmi_test_devices(uts, &dev); + if (ret) + return ret; + + scmi_devices = sandbox_scmi_devices_ctx(dev); + scmi_ctx = sandbox_scmi_service_ctx(); + agent0 = scmi_ctx->agent[0]; + agent1 = scmi_ctx->agent[1]; + + /* Test SCMI clocks rate manipulation */ + ut_asserteq(1000, clk_get_rate(&scmi_devices->clk[0])); + ut_asserteq(333, clk_get_rate(&scmi_devices->clk[1])); + ut_asserteq(44, clk_get_rate(&scmi_devices->clk[2])); + + ret_dev = clk_set_rate(&scmi_devices->clk[1], 1088); + ut_assert(!ret_dev || ret_dev == 1088); + + ut_asserteq(1000, agent0->clk[0].rate); + ut_asserteq(1088, agent0->clk[1].rate); + ut_asserteq(44, agent1->clk[0].rate); + + ut_asserteq(1000, clk_get_rate(&scmi_devices->clk[0])); + ut_asserteq(1088, clk_get_rate(&scmi_devices->clk[1])); + ut_asserteq(44, clk_get_rate(&scmi_devices->clk[2])); + + /* restore original rate for further tests */ + ret_dev = clk_set_rate(&scmi_devices->clk[1], 333); + ut_assert(!ret_dev || ret_dev == 333); + + /* Test SCMI clocks gating manipulation */ + ut_assert(!agent0->clk[0].enabled); + ut_assert(!agent0->clk[1].enabled); + ut_assert(!agent1->clk[0].enabled); + + ut_asserteq(0, clk_enable(&scmi_devices->clk[1])); + ut_asserteq(0, clk_enable(&scmi_devices->clk[2])); + + ut_assert(!agent0->clk[0].enabled); + ut_assert(agent0->clk[1].enabled); + ut_assert(agent1->clk[0].enabled); + + ut_assertok(clk_disable(&scmi_devices->clk[1])); + ut_assertok(clk_disable(&scmi_devices->clk[2])); + + ut_assert(!agent0->clk[0].enabled); + ut_assert(!agent0->clk[1].enabled); + ut_assert(!agent1->clk[0].enabled); + + return release_sandbox_scmi_test_devices(uts, dev); +} +DM_TEST(dm_test_scmi_clocks, UT_TESTF_SCAN_FDT); + +static int dm_test_scmi_resets(struct unit_test_state *uts) +{ + struct sandbox_scmi_devices *scmi_devices; + struct sandbox_scmi_service *scmi_ctx; + struct sandbox_scmi_agent *agent0; + struct udevice *dev = NULL; + int ret; + + ret = load_sandbox_scmi_test_devices(uts, &dev); + if (ret) + return ret; + + scmi_devices = sandbox_scmi_devices_ctx(dev); + scmi_ctx = sandbox_scmi_service_ctx(); + agent0 = scmi_ctx->agent[0]; + + /* Test SCMI resect controller manipulation */ + ut_assert(!agent0->reset[0].asserted) + + ut_assertok(reset_assert(&scmi_devices->reset[0])); + ut_assert(agent0->reset[0].asserted) + + ut_assertok(reset_deassert(&scmi_devices->reset[0])); + ut_assert(!agent0->reset[0].asserted); + + return release_sandbox_scmi_test_devices(uts, dev); +} +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); diff --git a/roms/u-boot/test/dm/serial.c b/roms/u-boot/test/dm/serial.c new file mode 100644 index 000000000..0662b5f09 --- /dev/null +++ b/roms/u-boot/test/dm/serial.c @@ -0,0 +1,72 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2018, STMicroelectronics + */ + +#include <common.h> +#include <log.h> +#include <serial.h> +#include <dm.h> +#include <dm/test.h> +#include <test/test.h> +#include <test/ut.h> + +static int dm_test_serial(struct unit_test_state *uts) +{ + struct serial_device_info info_serial = {0}; + struct udevice *dev_serial; + uint value_serial; + + ut_assertok(uclass_get_device_by_name(UCLASS_SERIAL, "serial", + &dev_serial)); + + ut_assertok(serial_tstc()); + /* + * test with default config which is the only one supported by + * sandbox_serial driver + */ + ut_assertok(serial_setconfig(dev_serial, SERIAL_DEFAULT_CONFIG)); + ut_assertok(serial_getconfig(dev_serial, &value_serial)); + ut_assert(value_serial == SERIAL_DEFAULT_CONFIG); + ut_assertok(serial_getinfo(dev_serial, &info_serial)); + ut_assert(info_serial.type == SERIAL_CHIP_UNKNOWN); + ut_assert(info_serial.addr == SERIAL_DEFAULT_ADDRESS); + ut_assert(info_serial.clock == SERIAL_DEFAULT_CLOCK); + /* + * test with a parameter which is NULL pointer + */ + ut_asserteq(-EINVAL, serial_getconfig(dev_serial, NULL)); + ut_asserteq(-EINVAL, serial_getinfo(dev_serial, NULL)); + /* + * test with a serial config which is not supported by + * sandbox_serial driver: test with wrong parity + */ + ut_asserteq(-ENOTSUPP, + serial_setconfig(dev_serial, + SERIAL_CONFIG(SERIAL_PAR_ODD, + SERIAL_8_BITS, + SERIAL_ONE_STOP))); + /* + * test with a serial config which is not supported by + * sandbox_serial driver: test with wrong bits number + */ + ut_asserteq(-ENOTSUPP, + serial_setconfig(dev_serial, + SERIAL_CONFIG(SERIAL_PAR_NONE, + SERIAL_6_BITS, + SERIAL_ONE_STOP))); + + /* + * test with a serial config which is not supported by + * sandbox_serial driver: test with wrong stop bits number + */ + ut_asserteq(-ENOTSUPP, + serial_setconfig(dev_serial, + SERIAL_CONFIG(SERIAL_PAR_NONE, + SERIAL_8_BITS, + SERIAL_TWO_STOP))); + + return 0; +} + +DM_TEST(dm_test_serial, UT_TESTF_SCAN_FDT); diff --git a/roms/u-boot/test/dm/sf.c b/roms/u-boot/test/dm/sf.c new file mode 100644 index 000000000..17d43fef3 --- /dev/null +++ b/roms/u-boot/test/dm/sf.c @@ -0,0 +1,104 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2013 Google, Inc + */ + +#include <common.h> +#include <command.h> +#include <dm.h> +#include <fdtdec.h> +#include <mapmem.h> +#include <os.h> +#include <spi.h> +#include <spi_flash.h> +#include <asm/state.h> +#include <asm/test.h> +#include <dm/test.h> +#include <dm/util.h> +#include <test/test.h> +#include <test/ut.h> + +/* Simple test of sandbox SPI flash */ +static int dm_test_spi_flash(struct unit_test_state *uts) +{ + struct udevice *dev, *emul; + int full_size = 0x200000; + int size = 0x10000; + u8 *src, *dst; + uint map_size; + ulong map_base; + uint offset; + int i; + + src = map_sysmem(0x20000, full_size); + ut_assertok(os_write_file("spi.bin", src, full_size)); + ut_assertok(uclass_first_device_err(UCLASS_SPI_FLASH, &dev)); + + dst = map_sysmem(0x20000 + full_size, full_size); + ut_assertok(spi_flash_read_dm(dev, 0, size, dst)); + ut_asserteq_mem(src, dst, size); + + /* Erase */ + ut_assertok(spi_flash_erase_dm(dev, 0, size)); + ut_assertok(spi_flash_read_dm(dev, 0, size, dst)); + for (i = 0; i < size; i++) + ut_asserteq(dst[i], 0xff); + + /* Write some new data */ + for (i = 0; i < size; i++) + src[i] = i; + ut_assertok(spi_flash_write_dm(dev, 0, size, src)); + ut_assertok(spi_flash_read_dm(dev, 0, size, dst)); + ut_asserteq_mem(src, dst, size); + + /* Try the write-protect stuff */ + ut_assertok(uclass_first_device_err(UCLASS_SPI_EMUL, &emul)); + ut_asserteq(0, spl_flash_get_sw_write_prot(dev)); + sandbox_sf_set_block_protect(emul, 1); + ut_asserteq(1, spl_flash_get_sw_write_prot(dev)); + sandbox_sf_set_block_protect(emul, 0); + ut_asserteq(0, spl_flash_get_sw_write_prot(dev)); + + /* Check mapping */ + ut_assertok(dm_spi_get_mmap(dev, &map_base, &map_size, &offset)); + ut_asserteq(0x1000, map_base); + ut_asserteq(0x2000, map_size); + ut_asserteq(0x100, offset); + + /* + * Since we are about to destroy all devices, we must tell sandbox + * to forget the emulation device + */ + sandbox_sf_unbind_emul(state_get_current(), 0, 0); + + return 0; +} +DM_TEST(dm_test_spi_flash, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); + +/* Functional test that sandbox SPI flash works correctly */ +static int dm_test_spi_flash_func(struct unit_test_state *uts) +{ + /* + * Create an empty test file and run the SPI flash tests. This is a + * long way from being a unit test, but it does test SPI device and + * emulator binding, probing, the SPI flash emulator including + * device tree decoding, plus the file-based backing store of SPI. + * + * More targeted tests could be created to perform the above steps + * one at a time. This might not increase test coverage much, but + * it would make bugs easier to find. It's not clear whether the + * benefit is worth the extra complexity. + */ + ut_asserteq(0, run_command_list( + "host save hostfs - 0 spi.bin 200000;" + "sf probe;" + "sf test 0 10000", -1, 0)); + /* + * Since we are about to destroy all devices, we must tell sandbox + * to forget the emulation device + */ + sandbox_sf_unbind_emul(state_get_current(), 0, 0); + + return 0; +} +DM_TEST(dm_test_spi_flash_func, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); diff --git a/roms/u-boot/test/dm/simple-bus.c b/roms/u-boot/test/dm/simple-bus.c new file mode 100644 index 000000000..3530b47fa --- /dev/null +++ b/roms/u-boot/test/dm/simple-bus.c @@ -0,0 +1,33 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2021, Bin Meng <bmeng.cn@gmail.com> + */ + +#include <common.h> +#include <dm.h> +#include <dm/test.h> +#include <dm/simple_bus.h> +#include <dm/uclass-internal.h> +#include <test/ut.h> + +static int dm_test_simple_bus(struct unit_test_state *uts) +{ + struct udevice *dev; + struct simple_bus_plat *plat; + + /* locate the dummy device @ translation-test node */ + ut_assertok(uclass_find_device_by_seq(UCLASS_TEST_DUMMY, 0, &dev)); + ut_asserteq_str("dev@0,0", dev->name); + + /* locate the parent node which is a simple-bus */ + ut_assertnonnull(dev = dev_get_parent(dev)); + ut_asserteq_str("translation-test@8000", dev->name); + + ut_assertnonnull(plat = dev_get_uclass_plat(dev)); + ut_asserteq(0, plat->base); + ut_asserteq(0x8000, plat->target); + ut_asserteq(0x1000, plat->size); + + return 0; +} +DM_TEST(dm_test_simple_bus, UT_TESTF_SCAN_FDT | UT_TESTF_FLAT_TREE); diff --git a/roms/u-boot/test/dm/simple-pm-bus.c b/roms/u-boot/test/dm/simple-pm-bus.c new file mode 100644 index 000000000..792c74505 --- /dev/null +++ b/roms/u-boot/test/dm/simple-pm-bus.c @@ -0,0 +1,45 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2020 Sean Anderson <seanga2@gmail.com> + */ + +#include <common.h> +#include <dm.h> +#include <dm/test.h> +#include <dm/device-internal.h> +#include <test/ut.h> +#include <asm/clk.h> +#include <asm/power-domain.h> + +/* These must match the ids in the device tree */ +#define TEST_CLOCK_ID 4 +#define TEST_POWER_ID 1 + +static int dm_test_simple_pm_bus(struct unit_test_state *uts) +{ + struct udevice *power; + struct udevice *clock; + struct udevice *bus; + + ut_assertok(uclass_get_device_by_name(UCLASS_POWER_DOMAIN, + "power-domain", &power)); + ut_assertok(uclass_get_device_by_name(UCLASS_CLK, "clk-sbox", + &clock)); + ut_asserteq(0, sandbox_power_domain_query(power, TEST_POWER_ID)); + ut_asserteq(0, sandbox_clk_query_enable(clock, TEST_CLOCK_ID)); + + ut_assertok(uclass_get_device_by_name(UCLASS_SIMPLE_BUS, "pm-bus-test", + &bus)); + ut_asserteq(1, sandbox_power_domain_query(power, TEST_POWER_ID)); + ut_asserteq(1, sandbox_clk_query_enable(clock, TEST_CLOCK_ID)); + + ut_assertok(device_remove(bus, DM_REMOVE_NORMAL)); + /* must re-probe since device_remove also removes the power domain */ + ut_assertok(uclass_get_device_by_name(UCLASS_POWER_DOMAIN, + "power-domain", &power)); + ut_asserteq(0, sandbox_power_domain_query(power, TEST_POWER_ID)); + ut_asserteq(0, sandbox_clk_query_enable(clock, TEST_CLOCK_ID)); + + return 0; +} +DM_TEST(dm_test_simple_pm_bus, UT_TESTF_SCAN_FDT); diff --git a/roms/u-boot/test/dm/smem.c b/roms/u-boot/test/dm/smem.c new file mode 100644 index 000000000..a797026cb --- /dev/null +++ b/roms/u-boot/test/dm/smem.c @@ -0,0 +1,28 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2018 Ramon Fried <ramon.fried@gmail.com> + */ + +#include <common.h> +#include <dm.h> +#include <smem.h> +#include <dm/test.h> +#include <test/test.h> +#include <test/ut.h> + +/* Basic test of the smem uclass */ +static int dm_test_smem_base(struct unit_test_state *uts) +{ + struct udevice *dev; + size_t size; + + ut_assertok(uclass_get_device(UCLASS_SMEM, 0, &dev)); + ut_assertnonnull(dev); + ut_assertok(smem_alloc(dev, -1, 0, 16)); + ut_asserteq(0, smem_get_free_space(dev, -1)); + ut_assertnull(smem_get(dev, -1, 0, &size)); + + return 0; +} +DM_TEST(dm_test_smem_base, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); + diff --git a/roms/u-boot/test/dm/soc.c b/roms/u-boot/test/dm/soc.c new file mode 100644 index 000000000..17e1b5ba0 --- /dev/null +++ b/roms/u-boot/test/dm/soc.c @@ -0,0 +1,120 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Test for the SOC uclass + * + * (C) Copyright 2020 - Texas Instruments Incorporated - http://www.ti.com/ + * Dave Gerlach <d-gerlach@ti.com> + */ + +#include <common.h> +#include <dm.h> +#include <dm/test.h> +#include <dm/uclass-internal.h> +#include <soc.h> +#include <test/ut.h> + +struct sb_soc_data { + unsigned long param; +}; + +static int dm_test_soc(struct unit_test_state *uts) +{ + struct udevice *dev; + char text[128]; + const struct soc_attr *soc_data; + const struct sb_soc_data *match_data; + + static const struct sb_soc_data soc_sandbox1_sr10_data = { 0x91919191 }; + static const struct sb_soc_data soc_sandbox123_data = { 0x84848484 }; + + static const struct soc_attr sb_soc_devices_full[] = { + { + .family = "SANDBOX0xx", + .machine = "SANDBOX012", + .revision = "1.0", + .data = NULL, + }, + { + .family = "SANDBOX1xx", + .machine = "SANDBOX107", + .revision = "1.0", + .data = NULL, + }, + { + .family = "SANDBOX1xx", + .machine = "SANDBOX123", + .revision = "1.0", + .data = &soc_sandbox123_data, + }, + { + .family = "SANDBOX1xx", + .machine = "SANDBOX131", + .revision = "2.0", + .data = NULL, + }, + { /* sentinel */ } + }; + + static const struct soc_attr sb_soc_devices_partial[] = { + { + .family = "SANDBOX0xx", + .revision = "1.0", + .data = NULL, + }, + { + .family = "SANDBOX1xx", + .revision = "1.0", + .data = &soc_sandbox1_sr10_data, + }, + { + .family = "SANDBOX1xx", + .revision = "2.0", + .data = NULL, + }, + { /* sentinel */ } + }; + + static const struct soc_attr sb_soc_devices_nomatch[] = { + { + .family = "SANDBOX0xx", + .revision = "1.0", + .data = NULL, + }, + { + .family = "SANDBOX1xx", + .revision = "2.0", + .data = NULL, + }, + { /* sentinel */ } + }; + + ut_assertok(soc_get(&dev)); + + ut_assertok(soc_get_machine(dev, text, sizeof(text))); + ut_assertok(strcmp(text, "SANDBOX123")); + + ut_assertok(soc_get_family(dev, text, sizeof(text))); + ut_assertok(strcmp(text, "SANDBOX1xx")); + + ut_assertok(soc_get_revision(dev, text, sizeof(text))); + ut_asserteq_str(text, "1.0"); + + soc_data = soc_device_match(sb_soc_devices_full); + ut_assert(soc_data); + + match_data = soc_data->data; + ut_asserteq(match_data->param, 0x84848484); + + soc_data = soc_device_match(sb_soc_devices_partial); + ut_assert(soc_data); + + match_data = soc_data->data; + ut_asserteq(match_data->param, 0x91919191); + + soc_data = soc_device_match(sb_soc_devices_nomatch); + ut_asserteq_ptr(soc_data, NULL); + + return 0; +} + +DM_TEST(dm_test_soc, UT_TESTF_SCAN_FDT); diff --git a/roms/u-boot/test/dm/sound.c b/roms/u-boot/test/dm/sound.c new file mode 100644 index 000000000..b73f6ab11 --- /dev/null +++ b/roms/u-boot/test/dm/sound.c @@ -0,0 +1,57 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright 2018 Google LLC + * Written by Simon Glass <sjg@chromium.org> + */ + +#include <common.h> +#include <dm.h> +#include <sound.h> +#include <dm/test.h> +#include <test/ut.h> +#include <test/test.h> +#include <asm/test.h> + +/* Basic test of the sound codec uclass */ +static int dm_test_sound(struct unit_test_state *uts) +{ + struct sound_uc_priv *uc_priv; + struct udevice *dev; + + /* check probe success */ + ut_assertok(uclass_first_device_err(UCLASS_SOUND, &dev)); + uc_priv = dev_get_uclass_priv(dev); + ut_asserteq_str("audio-codec", uc_priv->codec->name); + ut_asserteq_str("i2s", uc_priv->i2s->name); + ut_asserteq(0, sandbox_get_setup_called(dev)); + + ut_assertok(sound_beep(dev, 1, 100)); + ut_asserteq(4560, sandbox_get_sound_sum(dev)); + ut_assertok(sound_beep(dev, 1, 100)); + ut_asserteq(9120, sandbox_get_sound_sum(dev)); + ut_asserteq(false, sandbox_get_sound_active(dev)); + + return 0; +} +DM_TEST(dm_test_sound, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); + +/* Test of the 'start beep' operations */ +static int dm_test_sound_beep(struct unit_test_state *uts) +{ + struct udevice *dev; + + /* check probe success */ + ut_assertok(uclass_first_device_err(UCLASS_SOUND, &dev)); + ut_asserteq(-ENOSYS, sound_start_beep(dev, 100)); + ut_asserteq(0, sandbox_get_beep_frequency(dev)); + + sandbox_set_allow_beep(dev, true); + ut_asserteq(0, sound_start_beep(dev, 100)); + ut_asserteq(100, sandbox_get_beep_frequency(dev)); + + ut_asserteq(0, sound_stop_beep(dev)); + ut_asserteq(0, sandbox_get_beep_frequency(dev)); + + return 0; +} +DM_TEST(dm_test_sound_beep, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); diff --git a/roms/u-boot/test/dm/spi.c b/roms/u-boot/test/dm/spi.c new file mode 100644 index 000000000..ee4ad3aba --- /dev/null +++ b/roms/u-boot/test/dm/spi.c @@ -0,0 +1,206 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2013 Google, Inc + */ + +#include <common.h> +#include <dm.h> +#include <fdtdec.h> +#include <spi.h> +#include <spi_flash.h> +#include <asm/state.h> +#include <asm/test.h> +#include <dm/device-internal.h> +#include <dm/test.h> +#include <dm/uclass-internal.h> +#include <dm/util.h> +#include <test/test.h> +#include <test/ut.h> + +/* Test that we can find buses and chip-selects */ +static int dm_test_spi_find(struct unit_test_state *uts) +{ + struct sandbox_state *state = state_get_current(); + struct spi_slave *slave; + struct udevice *bus, *dev; + const int busnum = 0, cs = 0, mode = 0, speed = 1000000, cs_b = 2; + struct spi_cs_info info; + ofnode node; + + /* + * The post_bind() method will bind devices to chip selects. Check + * this then remove the emulation and the slave device. + */ + ut_asserteq(0, uclass_get_device_by_seq(UCLASS_SPI, busnum, &bus)); + ut_assertok(spi_cs_info(bus, cs, &info)); + node = dev_ofnode(info.dev); + device_remove(info.dev, DM_REMOVE_NORMAL); + device_unbind(info.dev); + + /* + * Even though the device is gone, the sandbox SPI drivers always + * reports that CS 0 is present + */ + ut_assertok(spi_cs_info(bus, cs, &info)); + ut_asserteq_ptr(NULL, info.dev); + + /* This finds nothing because we removed the device */ + ut_asserteq(-ENODEV, spi_find_bus_and_cs(busnum, cs, &bus, &dev)); + ut_asserteq(-ENODEV, spi_get_bus_and_cs(busnum, cs, speed, mode, + NULL, 0, &bus, &slave)); + + /* + * This forces the device to be re-added, but there is no emulation + * connected so the probe will fail. We require that bus is left + * alone on failure, and that the spi_get_bus_and_cs() does not add + * a 'partially-inited' device. + */ + ut_asserteq(-ENODEV, spi_find_bus_and_cs(busnum, cs, &bus, &dev)); + ut_asserteq(-ENOENT, spi_get_bus_and_cs(busnum, cs, speed, mode, + "jedec_spi_nor", "name", &bus, + &slave)); + sandbox_sf_unbind_emul(state_get_current(), busnum, cs); + ut_assertok(spi_cs_info(bus, cs, &info)); + ut_asserteq_ptr(NULL, info.dev); + + /* Add the emulation and try again */ + ut_assertok(sandbox_sf_bind_emul(state, busnum, cs, bus, node, + "name")); + ut_assertok(spi_find_bus_and_cs(busnum, cs, &bus, &dev)); + ut_assertok(spi_get_bus_and_cs(busnum, cs, speed, mode, + "jedec_spi_nor", "name", &bus, &slave)); + + ut_assertok(spi_cs_info(bus, cs, &info)); + ut_asserteq_ptr(info.dev, slave->dev); + + /* We should be able to add something to another chip select */ + ut_assertok(sandbox_sf_bind_emul(state, busnum, cs_b, bus, node, + "name")); + ut_asserteq(-EINVAL, spi_get_bus_and_cs(busnum, cs_b, speed, mode, + "jedec_spi_nor", "name", &bus, &slave)); + ut_asserteq(-EINVAL, spi_cs_info(bus, cs_b, &info)); + ut_asserteq_ptr(NULL, info.dev); + + /* + * Since we are about to destroy all devices, we must tell sandbox + * to forget the emulation device + */ + sandbox_sf_unbind_emul(state_get_current(), busnum, cs); + sandbox_sf_unbind_emul(state_get_current(), busnum, cs_b); + + return 0; +} +DM_TEST(dm_test_spi_find, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); + +/* dm_test_spi_switch_slaves - Helper function to check whether spi_claim_bus + * operates correctly with two spi slaves. + * + * Check that switching back and forth between two slaves claiming the bus + * will update dm_spi_bus->speed and sandbox_spi bus speed/mode correctly. + * + * @uts - unit test state + * @slave_a - first spi slave used for testing + * @slave_b - second spi slave used for testing + */ +static int dm_test_spi_switch_slaves(struct unit_test_state *uts, + struct spi_slave *slave_a, + struct spi_slave *slave_b) +{ + struct udevice *bus; + struct dm_spi_bus *bus_data; + + /* Check that slaves are on the same bus */ + ut_asserteq_ptr(dev_get_parent(slave_a->dev), + dev_get_parent(slave_b->dev)); + + bus = dev_get_parent(slave_a->dev); + bus_data = dev_get_uclass_priv(bus); + + ut_assertok(spi_claim_bus(slave_a)); + ut_asserteq(slave_a->max_hz, bus_data->speed); + ut_asserteq(slave_a->max_hz, sandbox_spi_get_speed(bus)); + ut_asserteq(slave_a->mode, sandbox_spi_get_mode(bus)); + spi_release_bus(slave_a); + + ut_assertok(spi_claim_bus(slave_b)); + ut_asserteq(slave_b->max_hz, bus_data->speed); + ut_asserteq(slave_b->max_hz, sandbox_spi_get_speed(bus)); + ut_asserteq(slave_b->mode, sandbox_spi_get_mode(bus)); + spi_release_bus(slave_b); + + ut_assertok(spi_claim_bus(slave_a)); + ut_asserteq(slave_a->max_hz, bus_data->speed); + ut_asserteq(slave_a->max_hz, sandbox_spi_get_speed(bus)); + ut_asserteq(slave_a->mode, sandbox_spi_get_mode(bus)); + spi_release_bus(slave_a); + + return 0; +} + +static int dm_test_spi_claim_bus(struct unit_test_state *uts) +{ + struct udevice *bus; + struct spi_slave *slave_a, *slave_b; + struct dm_spi_slave_plat *slave_plat; + const int busnum = 0, cs_a = 0, cs_b = 1, mode = 0; + + /* Get spi slave on CS0 */ + ut_assertok(spi_get_bus_and_cs(busnum, cs_a, 1000000, mode, NULL, 0, + &bus, &slave_a)); + /* Get spi slave on CS1 */ + ut_assertok(spi_get_bus_and_cs(busnum, cs_b, 1000000, mode, NULL, 0, + &bus, &slave_b)); + + /* Different max_hz, different mode. */ + ut_assert(slave_a->max_hz != slave_b->max_hz); + ut_assert(slave_a->mode != slave_b->mode); + dm_test_spi_switch_slaves(uts, slave_a, slave_b); + + /* Different max_hz, same mode. */ + slave_a->mode = slave_b->mode; + dm_test_spi_switch_slaves(uts, slave_a, slave_b); + + /* + * Same max_hz, different mode. + * Restore original mode for slave_a, from platdata. + */ + slave_plat = dev_get_parent_plat(slave_a->dev); + slave_a->mode = slave_plat->mode; + slave_a->max_hz = slave_b->max_hz; + dm_test_spi_switch_slaves(uts, slave_a, slave_b); + + return 0; +} +DM_TEST(dm_test_spi_claim_bus, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); + +/* Test that sandbox SPI works correctly */ +static int dm_test_spi_xfer(struct unit_test_state *uts) +{ + struct spi_slave *slave; + struct udevice *bus; + const int busnum = 0, cs = 0, mode = 0; + const char dout[5] = {0x9f}; + unsigned char din[5]; + + ut_assertok(spi_get_bus_and_cs(busnum, cs, 1000000, mode, NULL, 0, + &bus, &slave)); + ut_assertok(spi_claim_bus(slave)); + ut_assertok(spi_xfer(slave, 40, dout, din, + SPI_XFER_BEGIN | SPI_XFER_END)); + ut_asserteq(0xff, din[0]); + ut_asserteq(0x20, din[1]); + ut_asserteq(0x20, din[2]); + ut_asserteq(0x15, din[3]); + spi_release_bus(slave); + + /* + * Since we are about to destroy all devices, we must tell sandbox + * to forget the emulation device + */ +#if CONFIG_IS_ENABLED(DM_SPI_FLASH) + sandbox_sf_unbind_emul(state_get_current(), busnum, cs); +#endif + + return 0; +} +DM_TEST(dm_test_spi_xfer, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); diff --git a/roms/u-boot/test/dm/spmi.c b/roms/u-boot/test/dm/spmi.c new file mode 100644 index 000000000..114fd2d22 --- /dev/null +++ b/roms/u-boot/test/dm/spmi.c @@ -0,0 +1,113 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * (C) Copyright 2015 Mateusz Kulikowski <mateusz.kulikowski@gmail.com> + */ + +#include <common.h> +#include <fdtdec.h> +#include <dm.h> +#include <malloc.h> +#include <dm/device.h> +#include <dm/root.h> +#include <dm/test.h> +#include <dm/util.h> +#include <power/pmic.h> +#include <spmi/spmi.h> +#include <asm/gpio.h> +#include <test/test.h> +#include <test/ut.h> + +/* Test if bus childs got probed propperly*/ +static int dm_test_spmi_probe(struct unit_test_state *uts) +{ + const char *name = "spmi@0"; + struct udevice *bus, *dev; + + ut_assertok(uclass_get_device(UCLASS_SPMI, 0, &bus)); + + /* Check bus name */ + ut_asserteq_str(name, bus->name); + + /* Check that it has some devices */ + ut_asserteq(device_has_children(bus), true); + + ut_assertok(device_find_first_child(bus, &dev)); + + /* There should be at least one child */ + ut_assertnonnull(dev); + + /* Check that only PMICs are connected to the bus */ + while (dev) { + ut_asserteq(device_get_uclass_id(dev), UCLASS_PMIC); + device_find_next_child(&dev); + } + + return 0; +} +DM_TEST(dm_test_spmi_probe, UT_TESTF_SCAN_FDT); + +/* Test if it's possible to read bus directly and indirectly */ +static int dm_test_spmi_access(struct unit_test_state *uts) +{ + const char *pmic_name = "pm8916@0"; + struct udevice *bus, *pmic; + + ut_assertok(uclass_get_device(UCLASS_SPMI, 0, &bus)); + + ut_assertok(device_get_child(bus, 0, &pmic)); + + /* Sanity check if it's proper PMIC */ + ut_asserteq_str(pmic_name, pmic->name); + + /* Read PMIC ID reg using SPMI bus - it assumes it has slaveID == 0*/ + ut_asserteq(spmi_reg_read(bus, 0, 0xC0, 0x4), 0x10); + ut_asserteq(spmi_reg_read(bus, 0, 0xC0, 0x5), 0x5); + + /* Read ID reg via pmic interface */ + ut_asserteq(pmic_reg_read(pmic, 0xC004), 0x10); + ut_asserteq(pmic_reg_read(pmic, 0xC005), 0x5); + + return 0; +} +DM_TEST(dm_test_spmi_access, UT_TESTF_SCAN_FDT); + + +/* Test if it's possible to access GPIO that should be in pmic */ +static int dm_test_spmi_access_peripheral(struct unit_test_state *uts) +{ + struct udevice *dev; + unsigned int offset, gpio; + const char *name; + int offset_count; + + /* Get second pin of PMIC GPIO */ + ut_assertok(gpio_lookup_name("spmi1", &dev, &offset, &gpio)); + + /* Check if PMIC is parent */ + ut_asserteq(device_get_uclass_id(dev->parent), UCLASS_PMIC); + + /* This should be second gpio */ + ut_asserteq(1, offset); + + name = gpio_get_bank_info(dev, &offset_count); + + /* Check bank name */ + ut_asserteq_str("spmi", name); + /* Check pin count */ + ut_asserteq(4, offset_count); + + ut_assertok(gpio_request(gpio, "testing")); + + /* Try to set/clear gpio */ + ut_assertok(gpio_direction_output(gpio, 0)); + ut_asserteq(gpio_get_value(gpio), 0); + ut_assertok(gpio_direction_output(gpio, 1)); + ut_asserteq(gpio_get_value(gpio), 1); + ut_assertok(gpio_direction_input(gpio)); + ut_asserteq(gpio_get_value(gpio), 1); + + ut_assertok(gpio_free(gpio)); + + return 0; +} +DM_TEST(dm_test_spmi_access_peripheral, UT_TESTF_SCAN_FDT); diff --git a/roms/u-boot/test/dm/syscon-reset.c b/roms/u-boot/test/dm/syscon-reset.c new file mode 100644 index 000000000..eeaddf883 --- /dev/null +++ b/roms/u-boot/test/dm/syscon-reset.c @@ -0,0 +1,59 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2020 Sean Anderson <seanga2@gmail.com> + */ + +#include <common.h> +#include <dm.h> +#include <dm/test.h> +#include <regmap.h> +#include <reset.h> +#include <syscon.h> +#include <test/ut.h> +#include <asm/test.h> +#include <linux/bitops.h> + +/* The following values must match the device tree */ +#define TEST_RESET_REG 1 +#define TEST_RESET_ASSERT_HIGH 0 +#define TEST_RESET_ASSERT (TEST_RESET_ASSERT_HIGH ? (u32)-1 : (u32)0) +#define TEST_RESET_DEASSERT (~TEST_RESET_ASSERT) + +#define TEST_RESET_VALID 15 +#define TEST_RESET_NOMASK 30 +#define TEST_RESET_OUTOFRANGE 60 + +static int dm_test_syscon_reset(struct unit_test_state *uts) +{ + struct regmap *map; + struct reset_ctl rst; + struct udevice *reset; + struct udevice *syscon; + struct udevice *syscon_reset; + uint reg; + + ut_assertok(uclass_get_device_by_name(UCLASS_MISC, "syscon-reset-test", + &reset)); + ut_assertok(uclass_get_device_by_name(UCLASS_SYSCON, "syscon@0", + &syscon)); + ut_assertok(uclass_get_device_by_name(UCLASS_RESET, "syscon-reset", + &syscon_reset)); + ut_assertok_ptr((map = syscon_get_regmap(syscon))); + + ut_asserteq(-EINVAL, reset_get_by_name(reset, "no_mask", &rst)); + ut_asserteq(-EINVAL, reset_get_by_name(reset, "out_of_range", &rst)); + ut_assertok(reset_get_by_name(reset, "valid", &rst)); + + sandbox_set_enable_memio(true); + ut_assertok(regmap_write(map, TEST_RESET_REG, TEST_RESET_DEASSERT)); + ut_assertok(reset_assert(&rst)); + ut_assertok(regmap_read(map, TEST_RESET_REG, ®)); + ut_asserteq(TEST_RESET_DEASSERT ^ BIT(TEST_RESET_VALID), reg); + + ut_assertok(reset_deassert(&rst)); + ut_assertok(regmap_read(map, TEST_RESET_REG, ®)); + ut_asserteq(TEST_RESET_DEASSERT, reg); + + return 0; +} +DM_TEST(dm_test_syscon_reset, UT_TESTF_SCAN_FDT); diff --git a/roms/u-boot/test/dm/syscon.c b/roms/u-boot/test/dm/syscon.c new file mode 100644 index 000000000..be2329723 --- /dev/null +++ b/roms/u-boot/test/dm/syscon.c @@ -0,0 +1,84 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2015 Google, Inc + */ + +#include <common.h> +#include <dm.h> +#include <log.h> +#include <syscon.h> +#include <regmap.h> +#include <asm/test.h> +#include <dm/test.h> +#include <linux/err.h> +#include <test/test.h> +#include <test/ut.h> + +/* Base test of system controllers */ +static int dm_test_syscon_base(struct unit_test_state *uts) +{ + struct udevice *dev; + + ut_assertok(uclass_get_device(UCLASS_SYSCON, 0, &dev)); + ut_asserteq(SYSCON0, dev->driver_data); + + ut_assertok(uclass_get_device(UCLASS_SYSCON, 1, &dev)); + ut_asserteq(SYSCON1, dev->driver_data); + + ut_asserteq(-ENODEV, uclass_get_device(UCLASS_SYSCON, 2, &dev)); + + return 0; +} +DM_TEST(dm_test_syscon_base, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); + +/* Test system controller finding */ +static int dm_test_syscon_by_driver_data(struct unit_test_state *uts) +{ + struct udevice *dev; + + ut_assertok(syscon_get_by_driver_data(SYSCON0, &dev)); + ut_asserteq(SYSCON0, dev->driver_data); + + ut_assertok(syscon_get_by_driver_data(SYSCON1, &dev)); + ut_asserteq(SYSCON1, dev->driver_data); + + ut_asserteq(-ENODEV, syscon_get_by_driver_data(2, &dev)); + + return 0; +} +DM_TEST(dm_test_syscon_by_driver_data, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); + +/* Test system controller by phandle */ +static int dm_test_syscon_by_phandle(struct unit_test_state *uts) +{ + struct udevice *dev; + struct regmap *map; + + ut_assertok(uclass_get_device_by_name(UCLASS_TEST_PROBE, "test4", + &dev)); + + ut_assertok_ptr(syscon_regmap_lookup_by_phandle(dev, "first-syscon")); + map = syscon_regmap_lookup_by_phandle(dev, "first-syscon"); + ut_assert(map); + ut_assert(!IS_ERR(map)); + ut_asserteq(1, map->range_count); + + ut_assertok_ptr(syscon_regmap_lookup_by_phandle(dev, + "second-sys-ctrl")); + map = syscon_regmap_lookup_by_phandle(dev, "second-sys-ctrl"); + ut_assert(map); + ut_assert(!IS_ERR(map)); + ut_asserteq(4, map->range_count); + + ut_assertok_ptr(syscon_regmap_lookup_by_phandle(dev, + "third-syscon")); + map = syscon_regmap_lookup_by_phandle(dev, "third-syscon"); + ut_assert(map); + ut_assert(!IS_ERR(map)); + ut_asserteq(4, map->range_count); + + ut_assert(IS_ERR(syscon_regmap_lookup_by_phandle(dev, "not-present"))); + + return 0; +} +DM_TEST(dm_test_syscon_by_phandle, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); diff --git a/roms/u-boot/test/dm/sysinfo-gpio.c b/roms/u-boot/test/dm/sysinfo-gpio.c new file mode 100644 index 000000000..2e494b3f3 --- /dev/null +++ b/roms/u-boot/test/dm/sysinfo-gpio.c @@ -0,0 +1,69 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2021 Sean Anderson <sean.anderson@seco.com> + */ + +#include <common.h> +#include <dm.h> +#include <log.h> +#include <sysinfo.h> +#include <asm/gpio.h> +#include <dm/test.h> +#include <test/test.h> +#include <test/ut.h> + +static int dm_test_sysinfo_gpio(struct unit_test_state *uts) +{ + char buf[64]; + int val; + struct udevice *sysinfo, *gpio; + + ut_assertok(uclass_get_device_by_name(UCLASS_SYSINFO, "sysinfo-gpio", + &sysinfo)); + ut_assertok(uclass_get_device_by_name(UCLASS_GPIO, "base-gpios", &gpio)); + + /* + * Set up pins: pull-up (1), pull-down (0) and floating (2). This should + * result in digits 2 0 1, i.e. 2 * 9 + 1 * 3 = 19 + */ + sandbox_gpio_set_flags(gpio, 15, GPIOD_EXT_PULL_UP); + sandbox_gpio_set_flags(gpio, 16, GPIOD_EXT_PULL_DOWN); + sandbox_gpio_set_flags(gpio, 17, 0); + ut_assertok(sysinfo_detect(sysinfo)); + ut_assertok(sysinfo_get_int(sysinfo, SYSINFO_ID_BOARD_MODEL, &val)); + ut_asserteq(19, val); + ut_assertok(sysinfo_get_str(sysinfo, SYSINFO_ID_BOARD_MODEL, sizeof(buf), + buf)); + ut_asserteq_str("rev_a", buf); + + /* + * Set up pins: floating (2), pull-up (1) and pull-down (0). This should + * result in digits 0 1 2, i.e. 1 * 3 + 2 = 5 + */ + sandbox_gpio_set_flags(gpio, 15, 0); + sandbox_gpio_set_flags(gpio, 16, GPIOD_EXT_PULL_UP); + sandbox_gpio_set_flags(gpio, 17, GPIOD_EXT_PULL_DOWN); + ut_assertok(sysinfo_detect(sysinfo)); + ut_assertok(sysinfo_get_int(sysinfo, SYSINFO_ID_BOARD_MODEL, &val)); + ut_asserteq(5, val); + ut_assertok(sysinfo_get_str(sysinfo, SYSINFO_ID_BOARD_MODEL, sizeof(buf), + buf)); + ut_asserteq_str("foo", buf); + + /* + * Set up pins: floating (2), pull-up (1) and pull-down (0). This should + * result in digits 1 2 0, i.e. 1 * 9 + 2 * 3 = 15 + */ + sandbox_gpio_set_flags(gpio, 15, GPIOD_EXT_PULL_DOWN); + sandbox_gpio_set_flags(gpio, 16, 0); + sandbox_gpio_set_flags(gpio, 17, GPIOD_EXT_PULL_UP); + ut_assertok(sysinfo_detect(sysinfo)); + ut_assertok(sysinfo_get_int(sysinfo, SYSINFO_ID_BOARD_MODEL, &val)); + ut_asserteq(15, val); + ut_assertok(sysinfo_get_str(sysinfo, SYSINFO_ID_BOARD_MODEL, sizeof(buf), + buf)); + ut_asserteq_str("unknown", buf); + + return 0; +} +DM_TEST(dm_test_sysinfo_gpio, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); diff --git a/roms/u-boot/test/dm/sysinfo.c b/roms/u-boot/test/dm/sysinfo.c new file mode 100644 index 000000000..96b3a8eba --- /dev/null +++ b/roms/u-boot/test/dm/sysinfo.c @@ -0,0 +1,64 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * (C) Copyright 2018 + * Mario Six, Guntermann & Drunck GmbH, mario.six@gdsys.cc + */ + +#include <common.h> +#include <dm.h> +#include <log.h> +#include <dm/test.h> +#include <sysinfo.h> +#include <test/test.h> +#include <test/ut.h> + +#include "../../drivers/sysinfo/sandbox.h" + +static int dm_test_sysinfo(struct unit_test_state *uts) +{ + struct udevice *sysinfo; + bool called_detect = false; + char str[64]; + int i; + + ut_assertok(sysinfo_get(&sysinfo)); + ut_assert(sysinfo); + + ut_asserteq(-EPERM, sysinfo_get_bool(sysinfo, BOOL_CALLED_DETECT, + &called_detect)); + ut_assert(!called_detect); + + sysinfo_detect(sysinfo); + + ut_assertok(sysinfo_get_bool(sysinfo, BOOL_CALLED_DETECT, + &called_detect)); + ut_assert(called_detect); + + ut_assertok(sysinfo_get_str(sysinfo, STR_VACATIONSPOT, sizeof(str), + str)); + ut_assertok(strcmp(str, "R'lyeh")); + + ut_assertok(sysinfo_get_int(sysinfo, INT_TEST1, &i)); + ut_asserteq(0, i); + + ut_assertok(sysinfo_get_int(sysinfo, INT_TEST2, &i)); + ut_asserteq(100, i); + + ut_assertok(sysinfo_get_str(sysinfo, STR_VACATIONSPOT, sizeof(str), + str)); + ut_assertok(strcmp(str, "Carcosa")); + + ut_assertok(sysinfo_get_int(sysinfo, INT_TEST1, &i)); + ut_asserteq(1, i); + + ut_assertok(sysinfo_get_int(sysinfo, INT_TEST2, &i)); + ut_asserteq(99, i); + + ut_assertok(sysinfo_get_str(sysinfo, STR_VACATIONSPOT, sizeof(str), + str)); + ut_assertok(strcmp(str, "Yuggoth")); + + return 0; +} + +DM_TEST(dm_test_sysinfo, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); diff --git a/roms/u-boot/test/dm/sysreset.c b/roms/u-boot/test/dm/sysreset.c new file mode 100644 index 000000000..691683c56 --- /dev/null +++ b/roms/u-boot/test/dm/sysreset.c @@ -0,0 +1,118 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2015 Google, Inc + */ + +#include <common.h> +#include <dm.h> +#include <sysreset.h> +#include <asm/state.h> +#include <asm/test.h> +#include <dm/test.h> +#include <test/test.h> +#include <test/ut.h> + +/* Test that we can use particular sysreset devices */ +static int dm_test_sysreset_base(struct unit_test_state *uts) +{ + struct sandbox_state *state = state_get_current(); + struct udevice *dev; + + /* Device 0 is the platform data device - it should never respond */ + ut_assertok(uclass_get_device(UCLASS_SYSRESET, 0, &dev)); + ut_asserteq(-ENODEV, sysreset_request(dev, SYSRESET_WARM)); + ut_asserteq(-ENODEV, sysreset_request(dev, SYSRESET_COLD)); + ut_asserteq(-ENODEV, sysreset_request(dev, SYSRESET_POWER)); + + /* Device 1 is the warm sysreset device */ + ut_assertok(uclass_get_device(UCLASS_SYSRESET, 1, &dev)); + ut_asserteq(-EACCES, sysreset_request(dev, SYSRESET_WARM)); + ut_asserteq(-ENOSYS, sysreset_request(dev, SYSRESET_COLD)); + ut_asserteq(-ENOSYS, sysreset_request(dev, SYSRESET_POWER)); + + state->sysreset_allowed[SYSRESET_WARM] = true; + ut_asserteq(-EINPROGRESS, sysreset_request(dev, SYSRESET_WARM)); + state->sysreset_allowed[SYSRESET_WARM] = false; + + /* Device 2 is the cold sysreset device */ + ut_assertok(uclass_get_device(UCLASS_SYSRESET, 2, &dev)); + ut_asserteq(-ENOSYS, sysreset_request(dev, SYSRESET_WARM)); + state->sysreset_allowed[SYSRESET_COLD] = false; + ut_asserteq(-EACCES, sysreset_request(dev, SYSRESET_COLD)); + state->sysreset_allowed[SYSRESET_COLD] = true; + state->sysreset_allowed[SYSRESET_POWER] = false; + ut_asserteq(-EACCES, sysreset_request(dev, SYSRESET_POWER)); + state->sysreset_allowed[SYSRESET_POWER] = true; + + return 0; +} +DM_TEST(dm_test_sysreset_base, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); + +static int dm_test_sysreset_get_status(struct unit_test_state *uts) +{ + struct udevice *dev; + char msg[64]; + + /* Device 1 is the warm sysreset device */ + ut_assertok(uclass_get_device(UCLASS_SYSRESET, 1, &dev)); + ut_assertok(sysreset_get_status(dev, msg, sizeof(msg))); + ut_asserteq_str("Reset Status: WARM", msg); + + /* Device 2 is the cold sysreset device */ + ut_assertok(uclass_get_device(UCLASS_SYSRESET, 2, &dev)); + ut_assertok(sysreset_get_status(dev, msg, sizeof(msg))); + ut_asserteq_str("Reset Status: COLD", msg); + + return 0; +} +DM_TEST(dm_test_sysreset_get_status, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); + +/* Test that we can walk through the sysreset devices */ +static int dm_test_sysreset_walk(struct unit_test_state *uts) +{ + struct sandbox_state *state = state_get_current(); + + /* If we generate a power sysreset, we will exit sandbox! */ + state->sysreset_allowed[SYSRESET_WARM] = false; + state->sysreset_allowed[SYSRESET_COLD] = false; + state->sysreset_allowed[SYSRESET_POWER] = false; + state->sysreset_allowed[SYSRESET_POWER_OFF] = false; + ut_asserteq(-EACCES, sysreset_walk(SYSRESET_WARM)); + ut_asserteq(-EACCES, sysreset_walk(SYSRESET_COLD)); + ut_asserteq(-EACCES, sysreset_walk(SYSRESET_POWER)); + ut_asserteq(-EACCES, sysreset_walk(SYSRESET_POWER_OFF)); + + /* + * Enable cold system reset - this should make cold system reset work, + * plus a warm system reset should be promoted to cold, since this is + * the next step along. + */ + state->sysreset_allowed[SYSRESET_WARM] = true; + ut_asserteq(-EINPROGRESS, sysreset_walk(SYSRESET_WARM)); + ut_asserteq(-EACCES, sysreset_walk(SYSRESET_COLD)); + ut_asserteq(-EACCES, sysreset_walk(SYSRESET_POWER)); + state->sysreset_allowed[SYSRESET_COLD] = true; + state->sysreset_allowed[SYSRESET_POWER] = true; + + return 0; +} +DM_TEST(dm_test_sysreset_walk, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); + +static int dm_test_sysreset_get_last(struct unit_test_state *uts) +{ + struct udevice *dev; + + /* Device 1 is the warm sysreset device */ + ut_assertok(uclass_get_device(UCLASS_SYSRESET, 1, &dev)); + ut_asserteq(SYSRESET_WARM, sysreset_get_last(dev)); + + /* Device 2 is the cold sysreset device */ + ut_assertok(uclass_get_device(UCLASS_SYSRESET, 2, &dev)); + ut_asserteq(SYSRESET_POWER, sysreset_get_last(dev)); + + /* This is device 0, the non-DT one */ + ut_asserteq(SYSRESET_POWER, sysreset_get_last_walk()); + + return 0; +} +DM_TEST(dm_test_sysreset_get_last, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); diff --git a/roms/u-boot/test/dm/tee.c b/roms/u-boot/test/dm/tee.c new file mode 100644 index 000000000..7a11bf891 --- /dev/null +++ b/roms/u-boot/test/dm/tee.c @@ -0,0 +1,220 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2018 Linaro Limited + */ + +#include <common.h> +#include <dm.h> +#include <log.h> +#include <malloc.h> +#include <dm/test.h> +#include <sandboxtee.h> +#include <tee.h> +#include <test/test.h> +#include <test/ut.h> +#include <tee/optee_ta_avb.h> +#include <tee/optee_ta_rpc_test.h> + +static int open_session(struct udevice *dev, u32 *session, + struct tee_optee_ta_uuid *uuid) +{ + struct tee_open_session_arg arg; + int rc; + + memset(&arg, 0, sizeof(arg)); + tee_optee_ta_uuid_to_octets(arg.uuid, uuid); + rc = tee_open_session(dev, &arg, 0, NULL); + if (rc) + return rc; + if (arg.ret) + return -EIO; + *session = arg.session; + + return 0; +} + +static int invoke_func_avb(struct udevice *dev, u32 session) +{ + struct tee_param param = { .attr = TEE_PARAM_ATTR_TYPE_VALUE_OUTPUT }; + struct tee_invoke_arg arg; + + memset(&arg, 0, sizeof(arg)); + arg.session = session; + arg.func = TA_AVB_CMD_READ_LOCK_STATE; + + if (tee_invoke_func(dev, &arg, 1, ¶m) || arg.ret) + return -1; + + return 0; +} + +static int invoke_func_rpc_test(struct udevice *dev, u32 session, + u64 op, u64 busnum, u64 chip_addr, + u64 xfer_flags, u8 *buf, size_t buf_size) +{ + struct tee_param param[2]; + struct tee_invoke_arg arg; + struct tee_shm *shm_buf; + int rc; + + memset(&arg, 0, sizeof(arg)); + arg.session = session; + arg.func = op; + + rc = tee_shm_alloc(dev, buf_size, + TEE_SHM_ALLOC, &shm_buf); + if (rc) + return rc; + + if (op == TA_RPC_TEST_CMD_I2C_WRITE) + memcpy(shm_buf->addr, buf, buf_size); + + memset(param, 0, sizeof(param)); + param[0].attr = TEE_PARAM_ATTR_TYPE_VALUE_INPUT; + param[0].u.value.a = busnum; + param[0].u.value.b = chip_addr; + param[0].u.value.c = xfer_flags; + param[1].attr = TEE_PARAM_ATTR_TYPE_MEMREF_INOUT; + param[1].u.memref.shm = shm_buf; + param[1].u.memref.size = buf_size; + + if (tee_invoke_func(dev, &arg, 2, param) || arg.ret) { + rc = -1; + goto out; + } + + if (op == TA_RPC_TEST_CMD_I2C_READ) + memcpy(buf, shm_buf->addr, buf_size); +out: + tee_shm_free(shm_buf); + return rc; +} + +static int match(struct tee_version_data *vers, const void *data) +{ + return vers->gen_caps & TEE_GEN_CAP_GP; +} + +struct test_tee_vars { + struct tee_shm *reg_shm; + struct tee_shm *alloc_shm; +}; + +static int test_tee(struct unit_test_state *uts, struct test_tee_vars *vars) +{ + struct tee_version_data vers; + struct udevice *dev; + struct sandbox_tee_state *state; + struct tee_optee_ta_uuid avb_uuid = TA_AVB_UUID; + u32 session = 0; + int rc; + u8 data[128]; + + dev = tee_find_device(NULL, match, NULL, &vers); + ut_assert(dev); + state = dev_get_priv(dev); + ut_assert(!state->session); + + rc = open_session(dev, &session, &avb_uuid); + ut_assert(!rc); + ut_assert(session == state->session); + + rc = invoke_func_avb(dev, session); + ut_assert(!rc); + + rc = tee_close_session(dev, session); + ut_assert(!rc); + ut_assert(!state->session); + + ut_assert(!state->num_shms); + rc = tee_shm_register(dev, data, sizeof(data), 0, &vars->reg_shm); + ut_assert(!rc); + ut_assert(state->num_shms == 1); + + rc = tee_shm_alloc(dev, 256, 0, &vars->alloc_shm); + ut_assert(!rc); + ut_assert(state->num_shms == 2); + + ut_assert(tee_shm_is_registered(vars->reg_shm, dev)); + ut_assert(tee_shm_is_registered(vars->alloc_shm, dev)); + + tee_shm_free(vars->reg_shm); + vars->reg_shm = NULL; + tee_shm_free(vars->alloc_shm); + vars->alloc_shm = NULL; + ut_assert(!state->num_shms); + + return rc; +} + +#define I2C_BUF_SIZE 64 + +static int test_tee_rpc(struct unit_test_state *uts) +{ + struct tee_version_data vers; + struct udevice *dev; + struct sandbox_tee_state *state; + struct tee_optee_ta_uuid rpc_test_uuid = TA_RPC_TEST_UUID; + u32 session = 0; + int rc; + + char *test_str = "Test string"; + u8 data[I2C_BUF_SIZE] = {0}; + u8 data_from_eeprom[I2C_BUF_SIZE] = {0}; + + /* Use sandbox I2C EEPROM emulation; bus: 0, chip: 0x2c */ + u64 bus = 0; + u64 chip = 0x2c; + u64 xfer_flags = 0; + + dev = tee_find_device(NULL, match, NULL, &vers); + ut_assert(dev); + state = dev_get_priv(dev); + ut_assert(!state->session); + + /* Test RPC call asking for I2C service */ + rc = open_session(dev, &session, &rpc_test_uuid); + ut_assert(!rc); + ut_assert(session == state->session); + + /* Write buffer */ + strncpy((char *)data, test_str, strlen(test_str)); + rc = invoke_func_rpc_test(dev, session, TA_RPC_TEST_CMD_I2C_WRITE, + bus, chip, xfer_flags, data, sizeof(data)); + ut_assert(!rc); + + /* Read buffer */ + rc = invoke_func_rpc_test(dev, session, TA_RPC_TEST_CMD_I2C_READ, + bus, chip, xfer_flags, data_from_eeprom, + sizeof(data_from_eeprom)); + ut_assert(!rc); + + /* Compare */ + ut_assert(!memcmp(data, data_from_eeprom, sizeof(data))); + + rc = tee_close_session(dev, session); + ut_assert(!rc); + ut_assert(!state->session); + + return rc; +} + +static int dm_test_tee(struct unit_test_state *uts) +{ + struct test_tee_vars vars = { NULL, NULL }; + int rc = test_tee(uts, &vars); + + if (rc) + goto out; + + if (IS_ENABLED(CONFIG_OPTEE_TA_RPC_TEST)) + rc = test_tee_rpc(uts); +out: + /* In case test_tee() asserts these may still remain allocated */ + tee_shm_free(vars.reg_shm); + tee_shm_free(vars.alloc_shm); + + return rc; +} + +DM_TEST(dm_test_tee, UT_TESTF_SCAN_FDT); diff --git a/roms/u-boot/test/dm/test-dm.c b/roms/u-boot/test/dm/test-dm.c new file mode 100644 index 000000000..9ba2ba23d --- /dev/null +++ b/roms/u-boot/test/dm/test-dm.c @@ -0,0 +1,51 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (c) 2013 Google, Inc + */ + +#include <common.h> +#include <command.h> +#include <console.h> +#include <dm.h> +#include <errno.h> +#include <log.h> +#include <malloc.h> +#include <asm/global_data.h> +#include <asm/state.h> +#include <dm/root.h> +#include <dm/uclass-internal.h> +#include <test/test.h> +#include <test/test.h> +#include <test/ut.h> + +DECLARE_GLOBAL_DATA_PTR; + +/** + * dm_test_run() - Run driver model tests + * + * Run all the available driver model tests, or a selection + * + * @test_name: Name of single test to run (e.g. "dm_test_fdt_pre_reloc" or just + * "fdt_pre_reloc"), or NULL to run all + * @return 0 if all tests passed, 1 if not + */ +static int dm_test_run(const char *test_name) +{ + struct unit_test *tests = UNIT_TEST_SUITE_START(dm_test); + const int n_ents = UNIT_TEST_SUITE_COUNT(dm_test); + int ret; + + ret = ut_run_list("driver model", "dm_test_", tests, n_ents, test_name); + + return ret ? CMD_RET_FAILURE : 0; +} + +int do_ut_dm(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) +{ + const char *test_name = NULL; + + if (argc > 1) + test_name = argv[1]; + + return dm_test_run(test_name); +} diff --git a/roms/u-boot/test/dm/test-driver.c b/roms/u-boot/test/dm/test-driver.c new file mode 100644 index 000000000..02cb974b0 --- /dev/null +++ b/roms/u-boot/test/dm/test-driver.c @@ -0,0 +1,200 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (c) 2013 Google, Inc + * + * (C) Copyright 2012 + * Pavel Herrmann <morpheus.ibis@gmail.com> + */ + +#include <common.h> +#include <dm.h> +#include <errno.h> +#include <log.h> +#include <malloc.h> +#include <asm/io.h> +#include <dm/device-internal.h> +#include <dm/test.h> +#include <test/test.h> +#include <test/ut.h> + +int dm_testdrv_op_count[DM_TEST_OP_COUNT]; + +static int testdrv_ping(struct udevice *dev, int pingval, int *pingret) +{ + const struct dm_test_pdata *pdata = dev_get_plat(dev); + struct dm_test_priv *priv = dev_get_priv(dev); + + *pingret = pingval + pdata->ping_add; + priv->ping_total += *pingret; + + return 0; +} + +static const struct test_ops test_ops = { + .ping = testdrv_ping, +}; + +static int test_bind(struct udevice *dev) +{ + struct unit_test_state *uts = test_get_state(); + + /* Private data should not be allocated */ + ut_assert(!dev_get_priv(dev)); + + dm_testdrv_op_count[DM_TEST_OP_BIND]++; + return 0; +} + +static int test_probe(struct udevice *dev) +{ + struct unit_test_state *uts = test_get_state(); + struct dm_test_priv *priv = dev_get_priv(dev); + + /* Private data should be allocated */ + ut_assert(priv); + + dm_testdrv_op_count[DM_TEST_OP_PROBE]++; + priv->ping_total += DM_TEST_START_TOTAL; + return 0; +} + +static int test_remove(struct udevice *dev) +{ + struct unit_test_state *uts = test_get_state(); + + /* Private data should still be allocated */ + ut_assert(dev_get_priv(dev)); + + dm_testdrv_op_count[DM_TEST_OP_REMOVE]++; + return 0; +} + +static int test_unbind(struct udevice *dev) +{ + struct unit_test_state *uts = test_get_state(); + + /* Private data should not be allocated */ + ut_assert(!dev_get_priv(dev)); + + dm_testdrv_op_count[DM_TEST_OP_UNBIND]++; + return 0; +} + +U_BOOT_DRIVER(test_drv) = { + .name = "test_drv", + .id = UCLASS_TEST, + .ops = &test_ops, + .bind = test_bind, + .probe = test_probe, + .remove = test_remove, + .unbind = test_unbind, + .priv_auto = sizeof(struct dm_test_priv), +}; + +U_BOOT_DRIVER(test2_drv) = { + .name = "test2_drv", + .id = UCLASS_TEST, + .ops = &test_ops, + .bind = test_bind, + .probe = test_probe, + .remove = test_remove, + .unbind = test_unbind, + .priv_auto = sizeof(struct dm_test_priv), +}; + +static int test_manual_drv_ping(struct udevice *dev, int pingval, int *pingret) +{ + *pingret = pingval + 2; + + return 0; +} + +static const struct test_ops test_manual_ops = { + .ping = test_manual_drv_ping, +}; + +static int test_manual_bind(struct udevice *dev) +{ + dm_testdrv_op_count[DM_TEST_OP_BIND]++; + + return 0; +} + +static int test_manual_probe(struct udevice *dev) +{ + struct unit_test_state *uts = test_get_state(); + + dm_testdrv_op_count[DM_TEST_OP_PROBE]++; + if (!uts->force_fail_alloc) + dev_set_priv(dev, calloc(1, sizeof(struct dm_test_priv))); + if (!dev_get_priv(dev)) + return -ENOMEM; + + return 0; +} + +static int test_manual_remove(struct udevice *dev) +{ + dm_testdrv_op_count[DM_TEST_OP_REMOVE]++; + return 0; +} + +static int test_manual_unbind(struct udevice *dev) +{ + dm_testdrv_op_count[DM_TEST_OP_UNBIND]++; + return 0; +} + +U_BOOT_DRIVER(test_manual_drv) = { + .name = "test_manual_drv", + .id = UCLASS_TEST, + .ops = &test_manual_ops, + .bind = test_manual_bind, + .probe = test_manual_probe, + .remove = test_manual_remove, + .unbind = test_manual_unbind, +}; + +U_BOOT_DRIVER(test_pre_reloc_drv) = { + .name = "test_pre_reloc_drv", + .id = UCLASS_TEST, + .ops = &test_manual_ops, + .bind = test_manual_bind, + .probe = test_manual_probe, + .remove = test_manual_remove, + .unbind = test_manual_unbind, + .flags = DM_FLAG_PRE_RELOC, +}; + +U_BOOT_DRIVER(test_act_dma_drv) = { + .name = "test_act_dma_drv", + .id = UCLASS_TEST, + .ops = &test_manual_ops, + .bind = test_manual_bind, + .probe = test_manual_probe, + .remove = test_manual_remove, + .unbind = test_manual_unbind, + .flags = DM_FLAG_ACTIVE_DMA, +}; + +U_BOOT_DRIVER(test_vital_clk_drv) = { + .name = "test_vital_clk_drv", + .id = UCLASS_TEST, + .ops = &test_manual_ops, + .bind = test_manual_bind, + .probe = test_manual_probe, + .remove = test_manual_remove, + .unbind = test_manual_unbind, + .flags = DM_FLAG_VITAL, +}; + +U_BOOT_DRIVER(test_act_dma_vital_clk_drv) = { + .name = "test_act_dma_vital_clk_drv", + .id = UCLASS_TEST, + .ops = &test_manual_ops, + .bind = test_manual_bind, + .probe = test_manual_probe, + .remove = test_manual_remove, + .unbind = test_manual_unbind, + .flags = DM_FLAG_VITAL | DM_FLAG_ACTIVE_DMA, +}; diff --git a/roms/u-boot/test/dm/test-fdt.c b/roms/u-boot/test/dm/test-fdt.c new file mode 100644 index 000000000..8866d4d95 --- /dev/null +++ b/roms/u-boot/test/dm/test-fdt.c @@ -0,0 +1,1200 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (c) 2013 Google, Inc + */ + +#include <common.h> +#include <dm.h> +#include <errno.h> +#include <fdtdec.h> +#include <log.h> +#include <malloc.h> +#include <asm/global_data.h> +#include <asm/io.h> +#include <dm/test.h> +#include <dm/root.h> +#include <dm/device-internal.h> +#include <dm/devres.h> +#include <dm/uclass-internal.h> +#include <dm/util.h> +#include <dm/lists.h> +#include <dm/of_access.h> +#include <linux/ioport.h> +#include <test/test.h> +#include <test/ut.h> + +DECLARE_GLOBAL_DATA_PTR; + +struct dm_testprobe_pdata { + int probe_err; +}; + +static int testprobe_drv_probe(struct udevice *dev) +{ + struct dm_testprobe_pdata *pdata = dev_get_plat(dev); + + return pdata->probe_err; +} + +static const struct udevice_id testprobe_ids[] = { + { .compatible = "denx,u-boot-probe-test" }, + { } +}; + +U_BOOT_DRIVER(testprobe_drv) = { + .name = "testprobe_drv", + .of_match = testprobe_ids, + .id = UCLASS_TEST_PROBE, + .probe = testprobe_drv_probe, + .plat_auto = sizeof(struct dm_testprobe_pdata), +}; + +UCLASS_DRIVER(testprobe) = { + .name = "testprobe", + .id = UCLASS_TEST_PROBE, + .flags = DM_UC_FLAG_SEQ_ALIAS, +}; + +struct dm_testdevres_pdata { + void *ptr; +}; + +struct dm_testdevres_priv { + void *ptr; + void *ptr_ofdata; +}; + +static int testdevres_drv_bind(struct udevice *dev) +{ + struct dm_testdevres_pdata *pdata = dev_get_plat(dev); + + pdata->ptr = devm_kmalloc(dev, TEST_DEVRES_SIZE, 0); + + return 0; +} + +static int testdevres_drv_of_to_plat(struct udevice *dev) +{ + struct dm_testdevres_priv *priv = dev_get_priv(dev); + + priv->ptr_ofdata = devm_kmalloc(dev, TEST_DEVRES_SIZE3, 0); + + return 0; +} + +static int testdevres_drv_probe(struct udevice *dev) +{ + struct dm_testdevres_priv *priv = dev_get_priv(dev); + + priv->ptr = devm_kmalloc(dev, TEST_DEVRES_SIZE2, 0); + + return 0; +} + +static const struct udevice_id testdevres_ids[] = { + { .compatible = "denx,u-boot-devres-test" }, + { } +}; + +U_BOOT_DRIVER(testdevres_drv) = { + .name = "testdevres_drv", + .of_match = testdevres_ids, + .id = UCLASS_TEST_DEVRES, + .bind = testdevres_drv_bind, + .of_to_plat = testdevres_drv_of_to_plat, + .probe = testdevres_drv_probe, + .plat_auto = sizeof(struct dm_testdevres_pdata), + .priv_auto = sizeof(struct dm_testdevres_priv), +}; + +UCLASS_DRIVER(testdevres) = { + .name = "testdevres", + .id = UCLASS_TEST_DEVRES, + .flags = DM_UC_FLAG_SEQ_ALIAS, +}; + +int dm_check_devices(struct unit_test_state *uts, int num_devices) +{ + struct udevice *dev; + int ret; + int i; + + /* + * Now check that the ping adds are what we expect. This is using the + * ping-add property in each node. + */ + for (i = 0; i < num_devices; i++) { + uint32_t base; + + ret = uclass_get_device(UCLASS_TEST_FDT, i, &dev); + ut_assert(!ret); + + /* + * Get the 'ping-expect' property, which tells us what the + * ping add should be. We don't use the plat because we + * want to test the code that sets that up + * (testfdt_drv_probe()). + */ + base = fdtdec_get_addr(gd->fdt_blob, dev_of_offset(dev), + "ping-expect"); + debug("dev=%d, base=%d: %s\n", i, base, + fdt_get_name(gd->fdt_blob, dev_of_offset(dev), NULL)); + + ut_assert(!dm_check_operations(uts, dev, base, + dev_get_priv(dev))); + } + + return 0; +} + +/* Test that FDT-based binding works correctly */ +static int dm_test_fdt(struct unit_test_state *uts) +{ + const int num_devices = 9; + struct udevice *dev; + struct uclass *uc; + int ret; + int i; + + ret = dm_extended_scan(false); + ut_assert(!ret); + + ret = uclass_get(UCLASS_TEST_FDT, &uc); + ut_assert(!ret); + + /* These are num_devices compatible root-level device tree nodes */ + ut_asserteq(num_devices, list_count_items(&uc->dev_head)); + + /* Each should have platform data but no private data */ + for (i = 0; i < num_devices; i++) { + ret = uclass_find_device(UCLASS_TEST_FDT, i, &dev); + ut_assert(!ret); + ut_assert(!dev_get_priv(dev)); + ut_assert(dev_get_plat(dev)); + } + + ut_assertok(dm_check_devices(uts, num_devices)); + + return 0; +} +DM_TEST(dm_test_fdt, 0); + +static int dm_test_alias_highest_id(struct unit_test_state *uts) +{ + int ret; + + ret = dev_read_alias_highest_id("ethernet"); + ut_asserteq(5, ret); + + ret = dev_read_alias_highest_id("gpio"); + ut_asserteq(3, ret); + + ret = dev_read_alias_highest_id("pci"); + ut_asserteq(2, ret); + + ret = dev_read_alias_highest_id("i2c"); + ut_asserteq(0, ret); + + ret = dev_read_alias_highest_id("deadbeef"); + ut_asserteq(-1, ret); + + return 0; +} +DM_TEST(dm_test_alias_highest_id, 0); + +static int dm_test_fdt_pre_reloc(struct unit_test_state *uts) +{ + struct uclass *uc; + int ret; + + ret = dm_scan_fdt(true); + ut_assert(!ret); + + ret = uclass_get(UCLASS_TEST_FDT, &uc); + ut_assert(!ret); + + /* + * These are 2 pre-reloc devices: + * one with "u-boot,dm-pre-reloc" property (a-test node), and the other + * one whose driver marked with DM_FLAG_PRE_RELOC flag (h-test node). + */ + ut_asserteq(2, list_count_items(&uc->dev_head)); + + return 0; +} +DM_TEST(dm_test_fdt_pre_reloc, 0); + +/* Test that sequence numbers are allocated properly */ +static int dm_test_fdt_uclass_seq(struct unit_test_state *uts) +{ + struct udevice *dev; + + /* A few basic santiy tests */ + ut_assertok(uclass_find_device_by_seq(UCLASS_TEST_FDT, 3, &dev)); + ut_asserteq_str("b-test", dev->name); + ut_asserteq(3, dev_seq(dev)); + + ut_assertok(uclass_find_device_by_seq(UCLASS_TEST_FDT, 8, &dev)); + ut_asserteq_str("a-test", dev->name); + ut_asserteq(8, dev_seq(dev)); + + /* + * This device has no alias so gets the next value after all available + * aliases. The last alias is testfdt12 + */ + ut_assertok(uclass_find_device_by_seq(UCLASS_TEST_FDT, 13, &dev)); + ut_asserteq_str("d-test", dev->name); + ut_asserteq(13, dev_seq(dev)); + + ut_asserteq(-ENODEV, uclass_find_device_by_seq(UCLASS_TEST_FDT, 9, + &dev)); + ut_asserteq_ptr(NULL, dev); + + /* Test aliases */ + ut_assertok(uclass_get_device_by_seq(UCLASS_TEST_FDT, 6, &dev)); + ut_asserteq_str("e-test", dev->name); + ut_asserteq(6, dev_seq(dev)); + + /* + * Note that c-test nodes are not probed since it is not a top-level + * node + */ + ut_assertok(uclass_get_device_by_seq(UCLASS_TEST_FDT, 3, &dev)); + ut_asserteq_str("b-test", dev->name); + ut_asserteq(3, dev_seq(dev)); + + /* + * d-test wants sequence number 3 also, but it can't have it because + * b-test gets it first. + */ + ut_assertok(uclass_get_device(UCLASS_TEST_FDT, 2, &dev)); + ut_asserteq_str("d-test", dev->name); + ut_asserteq(13, dev_seq(dev)); + + /* g-test gets the next value after f-test */ + ut_assertok(uclass_get_device_by_seq(UCLASS_TEST_FDT, 15, &dev)); + ut_asserteq_str("g-test", dev->name); + ut_asserteq(15, dev_seq(dev)); + + /* And we should still have holes in our sequence numbers */ + ut_asserteq(-ENODEV, uclass_find_device_by_seq(UCLASS_TEST_FDT, 0, + &dev)); + ut_asserteq(-ENODEV, uclass_find_device_by_seq(UCLASS_TEST_FDT, 1, + &dev)); + ut_asserteq(-ENODEV, uclass_find_device_by_seq(UCLASS_TEST_FDT, 2, + &dev)); + ut_asserteq(-ENODEV, uclass_find_device_by_seq(UCLASS_TEST_FDT, 4, + &dev)); + ut_asserteq(-ENODEV, uclass_find_device_by_seq(UCLASS_TEST_FDT, 7, + &dev)); + ut_asserteq(-ENODEV, uclass_find_device_by_seq(UCLASS_TEST_FDT, 9, + &dev)); + ut_asserteq(-ENODEV, uclass_find_device_by_seq(UCLASS_TEST_FDT, 10, + &dev)); + ut_asserteq(-ENODEV, uclass_find_device_by_seq(UCLASS_TEST_FDT, 11, + &dev)); + + return 0; +} +DM_TEST(dm_test_fdt_uclass_seq, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); + +/* More tests for sequence numbers */ +static int dm_test_fdt_uclass_seq_manual(struct unit_test_state *uts) +{ + struct udevice *dev; + + /* + * Since DM_UC_FLAG_NO_AUTO_SEQ is set for this uclass, only testfdtm1 + * should get a sequence number assigned + */ + ut_assertok(uclass_get_device(UCLASS_TEST_FDT_MANUAL, 0, &dev)); + ut_asserteq_str("testfdtm0", dev->name); + ut_asserteq(-1, dev_seq(dev)); + + ut_assertok(uclass_get_device_by_seq(UCLASS_TEST_FDT_MANUAL, 1, &dev)); + ut_asserteq_str("testfdtm1", dev->name); + ut_asserteq(1, dev_seq(dev)); + + ut_assertok(uclass_get_device(UCLASS_TEST_FDT_MANUAL, 2, &dev)); + ut_asserteq_str("testfdtm2", dev->name); + ut_asserteq(-1, dev_seq(dev)); + + return 0; +} +DM_TEST(dm_test_fdt_uclass_seq_manual, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); + +static int dm_test_fdt_uclass_seq_more(struct unit_test_state *uts) +{ + struct udevice *dev; + ofnode node; + + /* Check creating a device with an alias */ + node = ofnode_path("/some-bus/c-test@1"); + ut_assertok(device_bind(dm_root(), DM_DRIVER_GET(denx_u_boot_fdt_test), + "c-test@1", NULL, node, &dev)); + ut_asserteq(12, dev_seq(dev)); + ut_assertok(uclass_get_device_by_seq(UCLASS_TEST_FDT, 12, &dev)); + ut_asserteq_str("c-test@1", dev->name); + + /* + * Now bind a device without an alias. It should not get the next + * sequence number after all aliases, and existing bound devices. The + * last alias is 12, so we have: + * + * 13 d-test + * 14 f-test + * 15 g-test + * 16 h-test + * 17 another-test + * 18 chosen-test + * + * So next available is 19 + */ + ut_assertok(device_bind(dm_root(), DM_DRIVER_GET(denx_u_boot_fdt_test), + "fred", NULL, ofnode_null(), &dev)); + ut_asserteq(19, dev_seq(dev)); + + ut_assertok(device_bind(dm_root(), DM_DRIVER_GET(denx_u_boot_fdt_test), + "fred2", NULL, ofnode_null(), &dev)); + ut_asserteq(20, dev_seq(dev)); + + return 0; +} +DM_TEST(dm_test_fdt_uclass_seq_more, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); + +/* Test that we can find a device by device tree offset */ +static int dm_test_fdt_offset(struct unit_test_state *uts) +{ + const void *blob = gd->fdt_blob; + struct udevice *dev; + int node; + + node = fdt_path_offset(blob, "/e-test"); + ut_assert(node > 0); + ut_assertok(uclass_get_device_by_of_offset(UCLASS_TEST_FDT, node, + &dev)); + ut_asserteq_str("e-test", dev->name); + + /* This node should not be bound */ + node = fdt_path_offset(blob, "/junk"); + ut_assert(node > 0); + ut_asserteq(-ENODEV, uclass_get_device_by_of_offset(UCLASS_TEST_FDT, + node, &dev)); + + /* This is not a top level node so should not be probed */ + node = fdt_path_offset(blob, "/some-bus/c-test@5"); + ut_assert(node > 0); + ut_asserteq(-ENODEV, uclass_get_device_by_of_offset(UCLASS_TEST_FDT, + node, &dev)); + + return 0; +} +DM_TEST(dm_test_fdt_offset, + UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT | UT_TESTF_FLAT_TREE); + +/** + * Test various error conditions with uclass_first_device() and + * uclass_next_device() + */ +static int dm_test_first_next_device(struct unit_test_state *uts) +{ + struct dm_testprobe_pdata *pdata; + struct udevice *dev, *parent = NULL; + int count; + int ret; + + /* There should be 4 devices */ + for (ret = uclass_first_device(UCLASS_TEST_PROBE, &dev), count = 0; + dev; + ret = uclass_next_device(&dev)) { + count++; + parent = dev_get_parent(dev); + } + ut_assertok(ret); + ut_asserteq(4, count); + + /* Remove them and try again, with an error on the second one */ + ut_assertok(uclass_get_device(UCLASS_TEST_PROBE, 1, &dev)); + pdata = dev_get_plat(dev); + pdata->probe_err = -ENOMEM; + device_remove(parent, DM_REMOVE_NORMAL); + ut_assertok(uclass_first_device(UCLASS_TEST_PROBE, &dev)); + ut_asserteq(-ENOMEM, uclass_next_device(&dev)); + ut_asserteq_ptr(dev, NULL); + + /* Now an error on the first one */ + ut_assertok(uclass_get_device(UCLASS_TEST_PROBE, 0, &dev)); + pdata = dev_get_plat(dev); + pdata->probe_err = -ENOENT; + device_remove(parent, DM_REMOVE_NORMAL); + ut_asserteq(-ENOENT, uclass_first_device(UCLASS_TEST_PROBE, &dev)); + + return 0; +} +DM_TEST(dm_test_first_next_device, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); + +/* Test iteration through devices in a uclass */ +static int dm_test_uclass_foreach(struct unit_test_state *uts) +{ + struct udevice *dev; + struct uclass *uc; + int count; + + count = 0; + uclass_id_foreach_dev(UCLASS_TEST_FDT, dev, uc) + count++; + ut_asserteq(9, count); + + count = 0; + uclass_foreach_dev(dev, uc) + count++; + ut_asserteq(9, count); + + return 0; +} +DM_TEST(dm_test_uclass_foreach, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); + +/** + * check_devices() - Check return values and pointers + * + * This runs through a full sequence of uclass_first_device_check()... + * uclass_next_device_check() checking that the return values and devices + * are correct. + * + * @uts: Test state + * @devlist: List of expected devices + * @mask: Indicates which devices should return an error. Device n should + * return error (-NOENT - n) if bit n is set, or no error (i.e. 0) if + * bit n is clear. + */ +static int check_devices(struct unit_test_state *uts, + struct udevice *devlist[], int mask) +{ + int expected_ret; + struct udevice *dev; + int i; + + expected_ret = (mask & 1) ? -ENOENT : 0; + mask >>= 1; + ut_asserteq(expected_ret, + uclass_first_device_check(UCLASS_TEST_PROBE, &dev)); + for (i = 0; i < 4; i++) { + ut_asserteq_ptr(devlist[i], dev); + expected_ret = (mask & 1) ? -ENOENT - (i + 1) : 0; + mask >>= 1; + ut_asserteq(expected_ret, uclass_next_device_check(&dev)); + } + ut_asserteq_ptr(NULL, dev); + + return 0; +} + +/* Test uclass_first_device_check() and uclass_next_device_check() */ +static int dm_test_first_next_ok_device(struct unit_test_state *uts) +{ + struct dm_testprobe_pdata *pdata; + struct udevice *dev, *parent = NULL, *devlist[4]; + int count; + int ret; + + /* There should be 4 devices */ + count = 0; + for (ret = uclass_first_device_check(UCLASS_TEST_PROBE, &dev); + dev; + ret = uclass_next_device_check(&dev)) { + ut_assertok(ret); + devlist[count++] = dev; + parent = dev_get_parent(dev); + } + ut_asserteq(4, count); + ut_assertok(uclass_first_device_check(UCLASS_TEST_PROBE, &dev)); + ut_assertok(check_devices(uts, devlist, 0)); + + /* Remove them and try again, with an error on the second one */ + pdata = dev_get_plat(devlist[1]); + pdata->probe_err = -ENOENT - 1; + device_remove(parent, DM_REMOVE_NORMAL); + ut_assertok(check_devices(uts, devlist, 1 << 1)); + + /* Now an error on the first one */ + pdata = dev_get_plat(devlist[0]); + pdata->probe_err = -ENOENT - 0; + device_remove(parent, DM_REMOVE_NORMAL); + ut_assertok(check_devices(uts, devlist, 3 << 0)); + + /* Now errors on all */ + pdata = dev_get_plat(devlist[2]); + pdata->probe_err = -ENOENT - 2; + pdata = dev_get_plat(devlist[3]); + pdata->probe_err = -ENOENT - 3; + device_remove(parent, DM_REMOVE_NORMAL); + ut_assertok(check_devices(uts, devlist, 0xf << 0)); + + return 0; +} +DM_TEST(dm_test_first_next_ok_device, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); + +static const struct udevice_id fdt_dummy_ids[] = { + { .compatible = "denx,u-boot-fdt-dummy", }, + { } +}; + +UCLASS_DRIVER(fdt_dummy) = { + .name = "fdt-dummy", + .id = UCLASS_TEST_DUMMY, + .flags = DM_UC_FLAG_SEQ_ALIAS, +}; + +U_BOOT_DRIVER(fdt_dummy_drv) = { + .name = "fdt_dummy_drv", + .of_match = fdt_dummy_ids, + .id = UCLASS_TEST_DUMMY, +}; + +static int dm_test_fdt_translation(struct unit_test_state *uts) +{ + struct udevice *dev; + fdt32_t dma_addr[2]; + + /* Some simple translations */ + ut_assertok(uclass_find_device_by_seq(UCLASS_TEST_DUMMY, 0, &dev)); + ut_asserteq_str("dev@0,0", dev->name); + ut_asserteq(0x8000, dev_read_addr(dev)); + + ut_assertok(uclass_find_device_by_seq(UCLASS_TEST_DUMMY, 1, &dev)); + ut_asserteq_str("dev@1,100", dev->name); + ut_asserteq(0x9000, dev_read_addr(dev)); + + ut_assertok(uclass_find_device_by_seq(UCLASS_TEST_DUMMY, 2, &dev)); + ut_asserteq_str("dev@2,200", dev->name); + ut_asserteq(0xA000, dev_read_addr(dev)); + + /* No translation for busses with #size-cells == 0 */ + ut_assertok(uclass_find_device_by_seq(UCLASS_TEST_DUMMY, 3, &dev)); + ut_asserteq_str("dev@42", dev->name); + ut_asserteq(0x42, dev_read_addr(dev)); + + /* dma address translation */ + ut_assertok(uclass_find_device_by_seq(UCLASS_TEST_DUMMY, 0, &dev)); + dma_addr[0] = cpu_to_be32(0); + dma_addr[1] = cpu_to_be32(0); + ut_asserteq(0x10000000, dev_translate_dma_address(dev, dma_addr)); + + ut_assertok(uclass_find_device_by_seq(UCLASS_TEST_DUMMY, 1, &dev)); + dma_addr[0] = cpu_to_be32(1); + dma_addr[1] = cpu_to_be32(0x100); + ut_asserteq(0x20000000, dev_translate_dma_address(dev, dma_addr)); + + return 0; +} +DM_TEST(dm_test_fdt_translation, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); + +static int dm_test_fdt_get_addr_ptr_flat(struct unit_test_state *uts) +{ + struct udevice *gpio, *dev; + void *ptr; + + /* Test for missing reg property */ + ut_assertok(uclass_first_device_err(UCLASS_GPIO, &gpio)); + ut_assertnull(devfdt_get_addr_ptr(gpio)); + + ut_assertok(uclass_find_device_by_seq(UCLASS_TEST_DUMMY, 0, &dev)); + ptr = devfdt_get_addr_ptr(dev); + ut_asserteq_ptr((void *)0x8000, ptr); + + return 0; +} +DM_TEST(dm_test_fdt_get_addr_ptr_flat, + UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT | UT_TESTF_FLAT_TREE); + +static int dm_test_fdt_remap_addr_flat(struct unit_test_state *uts) +{ + struct udevice *dev; + fdt_addr_t addr; + void *paddr; + + ut_assertok(uclass_find_device_by_seq(UCLASS_TEST_DUMMY, 0, &dev)); + + addr = devfdt_get_addr(dev); + ut_asserteq(0x8000, addr); + + paddr = map_physmem(addr, 0, MAP_NOCACHE); + ut_assertnonnull(paddr); + ut_asserteq_ptr(paddr, devfdt_remap_addr(dev)); + + return 0; +} +DM_TEST(dm_test_fdt_remap_addr_flat, + UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT | UT_TESTF_FLAT_TREE); + +static int dm_test_fdt_remap_addr_index_flat(struct unit_test_state *uts) +{ + struct udevice *dev; + fdt_addr_t addr; + fdt_size_t size; + void *paddr; + + ut_assertok(uclass_find_device_by_seq(UCLASS_TEST_DUMMY, 0, &dev)); + + addr = devfdt_get_addr_size_index(dev, 0, &size); + ut_asserteq(0x8000, addr); + ut_asserteq(0x1000, size); + + paddr = map_physmem(addr, 0, MAP_NOCACHE); + ut_assertnonnull(paddr); + ut_asserteq_ptr(paddr, devfdt_remap_addr_index(dev, 0)); + + return 0; +} +DM_TEST(dm_test_fdt_remap_addr_index_flat, + UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT | UT_TESTF_FLAT_TREE); + +static int dm_test_fdt_remap_addr_name_flat(struct unit_test_state *uts) +{ + struct udevice *dev; + fdt_addr_t addr; + fdt_size_t size; + void *paddr; + + ut_assertok(uclass_find_device_by_seq(UCLASS_TEST_DUMMY, 0, &dev)); + + addr = devfdt_get_addr_size_name(dev, "sandbox-dummy-0", &size); + ut_asserteq(0x8000, addr); + ut_asserteq(0x1000, size); + + paddr = map_physmem(addr, 0, MAP_NOCACHE); + ut_assertnonnull(paddr); + ut_asserteq_ptr(paddr, devfdt_remap_addr_name(dev, "sandbox-dummy-0")); + + return 0; +} +DM_TEST(dm_test_fdt_remap_addr_name_flat, + UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT | UT_TESTF_FLAT_TREE); + +static int dm_test_fdt_remap_addr_live(struct unit_test_state *uts) +{ + struct udevice *dev; + fdt_addr_t addr; + void *paddr; + + ut_assertok(uclass_find_device_by_seq(UCLASS_TEST_DUMMY, 0, &dev)); + + addr = dev_read_addr(dev); + ut_asserteq(0x8000, addr); + + paddr = map_physmem(addr, 0, MAP_NOCACHE); + ut_assertnonnull(paddr); + ut_asserteq_ptr(paddr, dev_remap_addr(dev)); + + return 0; +} +DM_TEST(dm_test_fdt_remap_addr_live, + UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); + +static int dm_test_fdt_remap_addr_index_live(struct unit_test_state *uts) +{ + struct udevice *dev; + fdt_addr_t addr; + fdt_size_t size; + void *paddr; + + ut_assertok(uclass_find_device_by_seq(UCLASS_TEST_DUMMY, 0, &dev)); + + addr = dev_read_addr_size_index(dev, 0, &size); + ut_asserteq(0x8000, addr); + ut_asserteq(0x1000, size); + + paddr = map_physmem(addr, 0, MAP_NOCACHE); + ut_assertnonnull(paddr); + ut_asserteq_ptr(paddr, dev_remap_addr_index(dev, 0)); + + return 0; +} +DM_TEST(dm_test_fdt_remap_addr_index_live, + UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); + +static int dm_test_fdt_remap_addr_name_live(struct unit_test_state *uts) +{ + struct udevice *dev; + fdt_addr_t addr; + fdt_size_t size; + void *paddr; + + ut_assertok(uclass_find_device_by_seq(UCLASS_TEST_DUMMY, 0, &dev)); + + addr = dev_read_addr_size_name(dev, "sandbox-dummy-0", &size); + ut_asserteq(0x8000, addr); + ut_asserteq(0x1000, size); + + paddr = map_physmem(addr, 0, MAP_NOCACHE); + ut_assertnonnull(paddr); + ut_asserteq_ptr(paddr, dev_remap_addr_name(dev, "sandbox-dummy-0")); + + return 0; +} +DM_TEST(dm_test_fdt_remap_addr_name_live, + UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); + +static int dm_test_fdt_livetree_writing(struct unit_test_state *uts) +{ + struct udevice *dev; + ofnode node; + + if (!of_live_active()) { + printf("Live tree not active; ignore test\n"); + return 0; + } + + /* Test enabling devices */ + + node = ofnode_path("/usb@2"); + + ut_assert(!of_device_is_available(ofnode_to_np(node))); + ofnode_set_enabled(node, true); + ut_assert(of_device_is_available(ofnode_to_np(node))); + + device_bind_driver_to_node(dm_root(), "usb_sandbox", "usb@2", node, + &dev); + ut_assertok(uclass_find_device_by_seq(UCLASS_USB, 2, &dev)); + + /* Test string property setting */ + + ut_assert(device_is_compatible(dev, "sandbox,usb")); + ofnode_write_string(node, "compatible", "gdsys,super-usb"); + ut_assert(device_is_compatible(dev, "gdsys,super-usb")); + ofnode_write_string(node, "compatible", "sandbox,usb"); + ut_assert(device_is_compatible(dev, "sandbox,usb")); + + /* Test setting generic properties */ + + /* Non-existent in DTB */ + ut_asserteq(FDT_ADDR_T_NONE, dev_read_addr(dev)); + /* reg = 0x42, size = 0x100 */ + ut_assertok(ofnode_write_prop(node, "reg", 8, + "\x00\x00\x00\x42\x00\x00\x01\x00")); + ut_asserteq(0x42, dev_read_addr(dev)); + + /* Test disabling devices */ + + device_remove(dev, DM_REMOVE_NORMAL); + device_unbind(dev); + + ut_assert(of_device_is_available(ofnode_to_np(node))); + ofnode_set_enabled(node, false); + ut_assert(!of_device_is_available(ofnode_to_np(node))); + + return 0; +} +DM_TEST(dm_test_fdt_livetree_writing, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); + +static int dm_test_fdt_disable_enable_by_path(struct unit_test_state *uts) +{ + ofnode node; + + if (!of_live_active()) { + printf("Live tree not active; ignore test\n"); + return 0; + } + + node = ofnode_path("/usb@2"); + + /* Test enabling devices */ + + ut_assert(!of_device_is_available(ofnode_to_np(node))); + dev_enable_by_path("/usb@2"); + ut_assert(of_device_is_available(ofnode_to_np(node))); + + /* Test disabling devices */ + + ut_assert(of_device_is_available(ofnode_to_np(node))); + dev_disable_by_path("/usb@2"); + ut_assert(!of_device_is_available(ofnode_to_np(node))); + + return 0; +} +DM_TEST(dm_test_fdt_disable_enable_by_path, UT_TESTF_SCAN_PDATA | + UT_TESTF_SCAN_FDT); + +/* Test a few uclass phandle functions */ +static int dm_test_fdt_phandle(struct unit_test_state *uts) +{ + struct udevice *back, *dev, *dev2; + + ut_assertok(uclass_find_first_device(UCLASS_PANEL_BACKLIGHT, &back)); + ut_assertnonnull(back); + ut_asserteq(-ENOENT, uclass_find_device_by_phandle(UCLASS_REGULATOR, + back, "missing", &dev)); + ut_assertok(uclass_find_device_by_phandle(UCLASS_REGULATOR, back, + "power-supply", &dev)); + ut_assertnonnull(dev); + ut_asserteq(0, device_active(dev)); + ut_asserteq_str("ldo1", dev->name); + ut_assertok(uclass_get_device_by_phandle(UCLASS_REGULATOR, back, + "power-supply", &dev2)); + ut_asserteq_ptr(dev, dev2); + + return 0; +} +DM_TEST(dm_test_fdt_phandle, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); + +/* Test device_find_first_child_by_uclass() */ +static int dm_test_first_child(struct unit_test_state *uts) +{ + struct udevice *i2c, *dev, *dev2; + + ut_assertok(uclass_first_device_err(UCLASS_I2C, &i2c)); + ut_assertok(device_find_first_child_by_uclass(i2c, UCLASS_RTC, &dev)); + ut_asserteq_str("rtc@43", dev->name); + ut_assertok(device_find_child_by_name(i2c, "rtc@43", &dev2)); + ut_asserteq_ptr(dev, dev2); + ut_assertok(device_find_child_by_name(i2c, "rtc@61", &dev2)); + ut_asserteq_str("rtc@61", dev2->name); + + ut_assertok(device_find_first_child_by_uclass(i2c, UCLASS_I2C_EEPROM, + &dev)); + ut_asserteq_str("eeprom@2c", dev->name); + ut_assertok(device_find_child_by_name(i2c, "eeprom@2c", &dev2)); + ut_asserteq_ptr(dev, dev2); + + ut_asserteq(-ENODEV, device_find_first_child_by_uclass(i2c, + UCLASS_VIDEO, &dev)); + ut_asserteq(-ENODEV, device_find_child_by_name(i2c, "missing", &dev)); + + return 0; +} +DM_TEST(dm_test_first_child, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); + +/* Test integer functions in dm_read_...() */ +static int dm_test_read_int(struct unit_test_state *uts) +{ + struct udevice *dev; + u32 val32; + s32 sval; + uint val; + u64 val64; + + ut_assertok(uclass_first_device_err(UCLASS_TEST_FDT, &dev)); + ut_asserteq_str("a-test", dev->name); + ut_assertok(dev_read_u32(dev, "int-value", &val32)); + ut_asserteq(1234, val32); + + ut_asserteq(-EINVAL, dev_read_u32(dev, "missing", &val32)); + ut_asserteq(6, dev_read_u32_default(dev, "missing", 6)); + + ut_asserteq(1234, dev_read_u32_default(dev, "int-value", 6)); + ut_asserteq(1234, val32); + + ut_asserteq(-EINVAL, dev_read_s32(dev, "missing", &sval)); + ut_asserteq(6, dev_read_s32_default(dev, "missing", 6)); + + ut_asserteq(-1234, dev_read_s32_default(dev, "uint-value", 6)); + ut_assertok(dev_read_s32(dev, "uint-value", &sval)); + ut_asserteq(-1234, sval); + + val = 0; + ut_asserteq(-EINVAL, dev_read_u32u(dev, "missing", &val)); + ut_assertok(dev_read_u32u(dev, "uint-value", &val)); + ut_asserteq(-1234, val); + + ut_assertok(dev_read_u64(dev, "int64-value", &val64)); + ut_asserteq_64(0x1111222233334444, val64); + + ut_asserteq_64(-EINVAL, dev_read_u64(dev, "missing", &val64)); + ut_asserteq_64(6, dev_read_u64_default(dev, "missing", 6)); + + ut_asserteq_64(0x1111222233334444, + dev_read_u64_default(dev, "int64-value", 6)); + + return 0; +} +DM_TEST(dm_test_read_int, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); + +static int dm_test_read_int_index(struct unit_test_state *uts) +{ + struct udevice *dev; + u32 val32; + + ut_assertok(uclass_first_device_err(UCLASS_TEST_FDT, &dev)); + ut_asserteq_str("a-test", dev->name); + + ut_asserteq(-EINVAL, dev_read_u32_index(dev, "missing", 0, &val32)); + ut_asserteq(19, dev_read_u32_index_default(dev, "missing", 0, 19)); + + ut_assertok(dev_read_u32_index(dev, "int-array", 0, &val32)); + ut_asserteq(5678, val32); + ut_assertok(dev_read_u32_index(dev, "int-array", 1, &val32)); + ut_asserteq(9123, val32); + ut_assertok(dev_read_u32_index(dev, "int-array", 2, &val32)); + ut_asserteq(4567, val32); + ut_asserteq(-EOVERFLOW, dev_read_u32_index(dev, "int-array", 3, + &val32)); + + ut_asserteq(5678, dev_read_u32_index_default(dev, "int-array", 0, 2)); + ut_asserteq(9123, dev_read_u32_index_default(dev, "int-array", 1, 2)); + ut_asserteq(4567, dev_read_u32_index_default(dev, "int-array", 2, 2)); + ut_asserteq(2, dev_read_u32_index_default(dev, "int-array", 3, 2)); + + return 0; +} +DM_TEST(dm_test_read_int_index, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); + +static int dm_test_read_phandle(struct unit_test_state *uts) +{ + struct udevice *dev; + struct ofnode_phandle_args args; + int ret; + const char prop[] = "test-gpios"; + const char cell[] = "#gpio-cells"; + const char prop2[] = "phandle-value"; + + ut_assertok(uclass_first_device_err(UCLASS_TEST_FDT, &dev)); + ut_asserteq_str("a-test", dev->name); + + /* Test dev_count_phandle_with_args with cell name */ + ret = dev_count_phandle_with_args(dev, "missing", cell, 0); + ut_asserteq(-ENOENT, ret); + ret = dev_count_phandle_with_args(dev, prop, "#invalid", 0); + ut_asserteq(-EINVAL, ret); + ut_asserteq(5, dev_count_phandle_with_args(dev, prop, cell, 0)); + + /* Test dev_read_phandle_with_args with cell name */ + ret = dev_read_phandle_with_args(dev, "missing", cell, 0, 0, &args); + ut_asserteq(-ENOENT, ret); + ret = dev_read_phandle_with_args(dev, prop, "#invalid", 0, 0, &args); + ut_asserteq(-EINVAL, ret); + ut_assertok(dev_read_phandle_with_args(dev, prop, cell, 0, 0, &args)); + ut_asserteq(1, args.args_count); + ut_asserteq(1, args.args[0]); + ut_assertok(dev_read_phandle_with_args(dev, prop, cell, 0, 1, &args)); + ut_asserteq(1, args.args_count); + ut_asserteq(4, args.args[0]); + ut_assertok(dev_read_phandle_with_args(dev, prop, cell, 0, 2, &args)); + ut_asserteq(5, args.args_count); + ut_asserteq(5, args.args[0]); + ut_asserteq(1, args.args[4]); + ret = dev_read_phandle_with_args(dev, prop, cell, 0, 3, &args); + ut_asserteq(-ENOENT, ret); + ut_assertok(dev_read_phandle_with_args(dev, prop, cell, 0, 4, &args)); + ut_asserteq(1, args.args_count); + ut_asserteq(12, args.args[0]); + ret = dev_read_phandle_with_args(dev, prop, cell, 0, 5, &args); + ut_asserteq(-ENOENT, ret); + + /* Test dev_count_phandle_with_args with cell count */ + ret = dev_count_phandle_with_args(dev, "missing", NULL, 2); + ut_asserteq(-ENOENT, ret); + ut_asserteq(3, dev_count_phandle_with_args(dev, prop2, NULL, 1)); + + /* Test dev_read_phandle_with_args with cell count */ + ut_assertok(dev_read_phandle_with_args(dev, prop2, NULL, 1, 0, &args)); + ut_asserteq(1, ofnode_valid(args.node)); + ut_asserteq(1, args.args_count); + ut_asserteq(10, args.args[0]); + ret = dev_read_phandle_with_args(dev, prop2, NULL, 1, 1, &args); + ut_asserteq(-EINVAL, ret); + ut_assertok(dev_read_phandle_with_args(dev, prop2, NULL, 1, 2, &args)); + ut_asserteq(1, ofnode_valid(args.node)); + ut_asserteq(1, args.args_count); + ut_asserteq(30, args.args[0]); + ret = dev_read_phandle_with_args(dev, prop2, NULL, 1, 3, &args); + ut_asserteq(-ENOENT, ret); + + return 0; +} +DM_TEST(dm_test_read_phandle, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); + +/* Test iteration through devices by drvdata */ +static int dm_test_uclass_drvdata(struct unit_test_state *uts) +{ + struct udevice *dev; + + ut_assertok(uclass_first_device_drvdata(UCLASS_TEST_FDT, + DM_TEST_TYPE_FIRST, &dev)); + ut_asserteq_str("a-test", dev->name); + + ut_assertok(uclass_first_device_drvdata(UCLASS_TEST_FDT, + DM_TEST_TYPE_SECOND, &dev)); + ut_asserteq_str("d-test", dev->name); + + ut_asserteq(-ENODEV, uclass_first_device_drvdata(UCLASS_TEST_FDT, + DM_TEST_TYPE_COUNT, + &dev)); + + return 0; +} +DM_TEST(dm_test_uclass_drvdata, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); + +/* Test device_first_child_ofdata_err(), etc. */ +static int dm_test_child_ofdata(struct unit_test_state *uts) +{ + struct udevice *bus, *dev; + int count; + + ut_assertok(uclass_first_device_err(UCLASS_TEST_BUS, &bus)); + count = 0; + device_foreach_child_of_to_plat(dev, bus) { + ut_assert(dev_get_flags(dev) & DM_FLAG_PLATDATA_VALID); + ut_assert(!(dev_get_flags(dev) & DM_FLAG_ACTIVATED)); + count++; + } + ut_asserteq(3, count); + + return 0; +} +DM_TEST(dm_test_child_ofdata, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); + +/* Test device_first_child_err(), etc. */ +static int dm_test_first_child_probe(struct unit_test_state *uts) +{ + struct udevice *bus, *dev; + int count; + + ut_assertok(uclass_first_device_err(UCLASS_TEST_BUS, &bus)); + count = 0; + device_foreach_child_probe(dev, bus) { + ut_assert(dev_get_flags(dev) & DM_FLAG_PLATDATA_VALID); + ut_assert(dev_get_flags(dev) & DM_FLAG_ACTIVATED); + count++; + } + ut_asserteq(3, count); + + return 0; +} +DM_TEST(dm_test_first_child_probe, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); + +/* Test that ofdata is read for parents before children */ +static int dm_test_ofdata_order(struct unit_test_state *uts) +{ + struct udevice *bus, *dev; + + ut_assertok(uclass_find_first_device(UCLASS_I2C, &bus)); + ut_assertnonnull(bus); + ut_assert(!(dev_get_flags(bus) & DM_FLAG_PLATDATA_VALID)); + + ut_assertok(device_find_first_child(bus, &dev)); + ut_assertnonnull(dev); + ut_assert(!(dev_get_flags(dev) & DM_FLAG_PLATDATA_VALID)); + + /* read the child's ofdata which should cause the parent's to be read */ + ut_assertok(device_of_to_plat(dev)); + ut_assert(dev_get_flags(dev) & DM_FLAG_PLATDATA_VALID); + ut_assert(dev_get_flags(bus) & DM_FLAG_PLATDATA_VALID); + + ut_assert(!(dev_get_flags(dev) & DM_FLAG_ACTIVATED)); + ut_assert(!(dev_get_flags(bus) & DM_FLAG_ACTIVATED)); + + return 0; +} +DM_TEST(dm_test_ofdata_order, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); + +/* Test dev_decode_display_timing() */ +static int dm_test_decode_display_timing(struct unit_test_state *uts) +{ + struct udevice *dev; + struct display_timing timing; + + ut_assertok(uclass_first_device_err(UCLASS_TEST_FDT, &dev)); + ut_asserteq_str("a-test", dev->name); + + ut_assertok(dev_decode_display_timing(dev, 0, &timing)); + ut_assert(timing.hactive.typ == 240); + ut_assert(timing.hback_porch.typ == 7); + ut_assert(timing.hfront_porch.typ == 6); + ut_assert(timing.hsync_len.typ == 1); + ut_assert(timing.vactive.typ == 320); + ut_assert(timing.vback_porch.typ == 5); + ut_assert(timing.vfront_porch.typ == 8); + ut_assert(timing.vsync_len.typ == 2); + ut_assert(timing.pixelclock.typ == 6500000); + ut_assert(timing.flags & DISPLAY_FLAGS_HSYNC_HIGH); + ut_assert(!(timing.flags & DISPLAY_FLAGS_HSYNC_LOW)); + ut_assert(!(timing.flags & DISPLAY_FLAGS_VSYNC_HIGH)); + ut_assert(timing.flags & DISPLAY_FLAGS_VSYNC_LOW); + ut_assert(timing.flags & DISPLAY_FLAGS_DE_HIGH); + ut_assert(!(timing.flags & DISPLAY_FLAGS_DE_LOW)); + ut_assert(timing.flags & DISPLAY_FLAGS_PIXDATA_POSEDGE); + ut_assert(!(timing.flags & DISPLAY_FLAGS_PIXDATA_NEGEDGE)); + ut_assert(timing.flags & DISPLAY_FLAGS_INTERLACED); + ut_assert(timing.flags & DISPLAY_FLAGS_DOUBLESCAN); + ut_assert(timing.flags & DISPLAY_FLAGS_DOUBLECLK); + + ut_assertok(dev_decode_display_timing(dev, 1, &timing)); + ut_assert(timing.hactive.typ == 480); + ut_assert(timing.hback_porch.typ == 59); + ut_assert(timing.hfront_porch.typ == 10); + ut_assert(timing.hsync_len.typ == 12); + ut_assert(timing.vactive.typ == 800); + ut_assert(timing.vback_porch.typ == 15); + ut_assert(timing.vfront_porch.typ == 17); + ut_assert(timing.vsync_len.typ == 16); + ut_assert(timing.pixelclock.typ == 9000000); + ut_assert(!(timing.flags & DISPLAY_FLAGS_HSYNC_HIGH)); + ut_assert(timing.flags & DISPLAY_FLAGS_HSYNC_LOW); + ut_assert(timing.flags & DISPLAY_FLAGS_VSYNC_HIGH); + ut_assert(!(timing.flags & DISPLAY_FLAGS_VSYNC_LOW)); + ut_assert(!(timing.flags & DISPLAY_FLAGS_DE_HIGH)); + ut_assert(timing.flags & DISPLAY_FLAGS_DE_LOW); + ut_assert(!(timing.flags & DISPLAY_FLAGS_PIXDATA_POSEDGE)); + ut_assert(timing.flags & DISPLAY_FLAGS_PIXDATA_NEGEDGE); + ut_assert(!(timing.flags & DISPLAY_FLAGS_INTERLACED)); + ut_assert(!(timing.flags & DISPLAY_FLAGS_DOUBLESCAN)); + ut_assert(!(timing.flags & DISPLAY_FLAGS_DOUBLECLK)); + + ut_assertok(dev_decode_display_timing(dev, 2, &timing)); + ut_assert(timing.hactive.typ == 800); + ut_assert(timing.hback_porch.typ == 89); + ut_assert(timing.hfront_porch.typ == 164); + ut_assert(timing.hsync_len.typ == 11); + ut_assert(timing.vactive.typ == 480); + ut_assert(timing.vback_porch.typ == 23); + ut_assert(timing.vfront_porch.typ == 10); + ut_assert(timing.vsync_len.typ == 13); + ut_assert(timing.pixelclock.typ == 33500000); + ut_assert(!(timing.flags & DISPLAY_FLAGS_HSYNC_HIGH)); + ut_assert(!(timing.flags & DISPLAY_FLAGS_HSYNC_LOW)); + ut_assert(!(timing.flags & DISPLAY_FLAGS_VSYNC_HIGH)); + ut_assert(!(timing.flags & DISPLAY_FLAGS_VSYNC_LOW)); + ut_assert(!(timing.flags & DISPLAY_FLAGS_DE_HIGH)); + ut_assert(!(timing.flags & DISPLAY_FLAGS_DE_LOW)); + ut_assert(!(timing.flags & DISPLAY_FLAGS_PIXDATA_POSEDGE)); + ut_assert(!(timing.flags & DISPLAY_FLAGS_PIXDATA_NEGEDGE)); + ut_assert(!(timing.flags & DISPLAY_FLAGS_INTERLACED)); + ut_assert(!(timing.flags & DISPLAY_FLAGS_DOUBLESCAN)); + ut_assert(!(timing.flags & DISPLAY_FLAGS_DOUBLECLK)); + + ut_assert(dev_decode_display_timing(dev, 3, &timing)); + return 0; +} +DM_TEST(dm_test_decode_display_timing, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); + +/* Test read_resourcee() */ +static int dm_test_read_resource(struct unit_test_state *uts) +{ + struct udevice *dev; + struct resource res; + + /* test resource without translation */ + ut_assertok(uclass_find_device_by_name(UCLASS_SIMPLE_BUS, "syscon@2", &dev)); + ut_assertok(dev_read_resource(dev, 0, &res)); + ut_asserteq(0x40, res.start); + ut_asserteq(0x44, res.end); + ut_assertok(dev_read_resource(dev, 1, &res)); + ut_asserteq(0x48, res.start); + ut_asserteq(0x4d, res.end); + + /* test resource with translation */ + ut_assertok(uclass_find_device_by_name(UCLASS_TEST_DUMMY, "dev@1,100", &dev)); + ut_assertok(dev_read_resource(dev, 0, &res)); + ut_asserteq(0x9000, res.start); + ut_asserteq(0x9fff, res.end); + + /* test named resource */ + ut_assertok(uclass_find_device_by_name(UCLASS_TEST_DUMMY, "dev@0,0", &dev)); + ut_assertok(dev_read_resource_byname(dev, "sandbox-dummy-0", &res)); + ut_asserteq(0x8000, res.start); + ut_asserteq(0x8fff, res.end); + + return 0; +} + +DM_TEST(dm_test_read_resource, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); diff --git a/roms/u-boot/test/dm/test-uclass.c b/roms/u-boot/test/dm/test-uclass.c new file mode 100644 index 000000000..067701734 --- /dev/null +++ b/roms/u-boot/test/dm/test-uclass.c @@ -0,0 +1,132 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (c) 2013 Google, Inc + * + * (C) Copyright 2012 + * Pavel Herrmann <morpheus.ibis@gmail.com> + */ + +#include <common.h> +#include <log.h> +#include <malloc.h> +#include <dm.h> +#include <errno.h> +#include <asm/io.h> +#include <dm/test.h> +#include <linux/list.h> +#include <test/test.h> +#include <test/ut.h> + +int test_ping(struct udevice *dev, int pingval, int *pingret) +{ + const struct test_ops *ops = device_get_ops(dev); + + if (!ops->ping) + return -ENOSYS; + + return ops->ping(dev, pingval, pingret); +} + +static int test_post_bind(struct udevice *dev) +{ + struct unit_test_state *uts = test_get_state(); + struct dm_test_perdev_uc_pdata *uc_pdata; + + dm_testdrv_op_count[DM_TEST_OP_POST_BIND]++; + ut_assert(!device_active(dev)); + + uc_pdata = dev_get_uclass_plat(dev); + ut_assert(uc_pdata); + + uc_pdata->intval1 = TEST_UC_PDATA_INTVAL1; + uc_pdata->intval2 = TEST_UC_PDATA_INTVAL2; + uc_pdata->intval3 = TEST_UC_PDATA_INTVAL3; + + return 0; +} + +static int test_pre_unbind(struct udevice *dev) +{ + dm_testdrv_op_count[DM_TEST_OP_PRE_UNBIND]++; + + return 0; +} + +static int test_pre_probe(struct udevice *dev) +{ + struct dm_test_uclass_perdev_priv *priv = dev_get_uclass_priv(dev); + struct unit_test_state *uts = test_get_state(); + + dm_testdrv_op_count[DM_TEST_OP_PRE_PROBE]++; + ut_assert(priv); + ut_assert(device_active(dev)); + + return 0; +} + +static int test_post_probe(struct udevice *dev) +{ + struct unit_test_state *uts = test_get_state(); + struct udevice *prev = list_entry(dev->uclass_node.prev, + struct udevice, uclass_node); + + struct dm_test_uclass_perdev_priv *priv = dev_get_uclass_priv(dev); + struct uclass *uc = dev->uclass; + + dm_testdrv_op_count[DM_TEST_OP_POST_PROBE]++; + ut_assert(priv); + ut_assert(device_active(dev)); + priv->base_add = 0; + if (uts->skip_post_probe) + return 0; + if (&prev->uclass_node != &uc->dev_head) { + struct dm_test_uclass_perdev_priv *prev_uc_priv + = dev_get_uclass_priv(prev); + struct dm_test_pdata *pdata = dev_get_plat(prev); + + ut_assert(pdata); + ut_assert(prev_uc_priv); + priv->base_add = prev_uc_priv->base_add + pdata->ping_add; + } + + return 0; +} + +static int test_pre_remove(struct udevice *dev) +{ + dm_testdrv_op_count[DM_TEST_OP_PRE_REMOVE]++; + + return 0; +} + +static int test_init(struct uclass *uc) +{ + struct unit_test_state *uts = test_get_state(); + + dm_testdrv_op_count[DM_TEST_OP_INIT]++; + ut_assert(uclass_get_priv(uc)); + + return 0; +} + +static int test_destroy(struct uclass *uc) +{ + dm_testdrv_op_count[DM_TEST_OP_DESTROY]++; + + return 0; +} + +UCLASS_DRIVER(test) = { + .name = "test", + .id = UCLASS_TEST, + .post_bind = test_post_bind, + .pre_unbind = test_pre_unbind, + .pre_probe = test_pre_probe, + .post_probe = test_post_probe, + .pre_remove = test_pre_remove, + .init = test_init, + .destroy = test_destroy, + .priv_auto = sizeof(struct dm_test_uclass_priv), + .per_device_auto = sizeof(struct dm_test_uclass_perdev_priv), + .per_device_plat_auto = sizeof(struct dm_test_perdev_uc_pdata), +}; diff --git a/roms/u-boot/test/dm/timer.c b/roms/u-boot/test/dm/timer.c new file mode 100644 index 000000000..70043b9ee --- /dev/null +++ b/roms/u-boot/test/dm/timer.c @@ -0,0 +1,50 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2015 Thomas Chou <thomas@wytron.com.tw> + */ + +#include <common.h> +#include <dm.h> +#include <timer.h> +#include <dm/test.h> +#include <dm/device-internal.h> +#include <test/test.h> +#include <test/ut.h> +#include <asm/cpu.h> + +/* + * Basic test of the timer uclass. + */ +static int dm_test_timer_base(struct unit_test_state *uts) +{ + struct udevice *dev; + + ut_assertok(uclass_get_device_by_name(UCLASS_TIMER, "timer@0", &dev)); + ut_asserteq(1000000, timer_get_rate(dev)); + + return 0; +} +DM_TEST(dm_test_timer_base, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); + +/* + * Test of timebase fallback + */ +static int dm_test_timer_timebase_fallback(struct unit_test_state *uts) +{ + struct udevice *dev; + + cpu_sandbox_set_current("cpu-test1"); + ut_assertok(uclass_get_device_by_name(UCLASS_TIMER, "timer@1", &dev)); + ut_asserteq(3000000, timer_get_rate(dev)); + ut_assertok(device_remove(dev, DM_REMOVE_NORMAL)); + + cpu_sandbox_set_current("cpu-test2"); + ut_assertok(uclass_get_device_by_name(UCLASS_TIMER, "timer@1", &dev)); + ut_asserteq(2000000, timer_get_rate(dev)); + + cpu_sandbox_set_current("cpu-test1"); + + return 0; +} +DM_TEST(dm_test_timer_timebase_fallback, + UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); diff --git a/roms/u-boot/test/dm/usb.c b/roms/u-boot/test/dm/usb.c new file mode 100644 index 000000000..5d6ceefce --- /dev/null +++ b/roms/u-boot/test/dm/usb.c @@ -0,0 +1,438 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2015 Google, Inc + */ + +#include <common.h> +#include <console.h> +#include <dm.h> +#include <part.h> +#include <usb.h> +#include <asm/io.h> +#include <asm/state.h> +#include <asm/test.h> +#include <dm/device-internal.h> +#include <dm/test.h> +#include <dm/uclass-internal.h> +#include <test/test.h> +#include <test/ut.h> + +struct keyboard_test_data { + const char modifiers; + const char scancode; + const char result[6]; +}; + +/* Test that sandbox USB works correctly */ +static int dm_test_usb_base(struct unit_test_state *uts) +{ + struct udevice *bus; + + ut_asserteq(-ENODEV, uclass_get_device_by_seq(UCLASS_USB, 0, &bus)); + ut_assertok(uclass_get_device(UCLASS_USB, 0, &bus)); + ut_asserteq(-ENODEV, uclass_get_device_by_seq(UCLASS_USB, 2, &bus)); + + return 0; +} +DM_TEST(dm_test_usb_base, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); + +/* + * Test that we can use the flash stick. This is more of a functional test. It + * covers scanning the bug, setting up a hub and a flash stick and reading + * data from the flash stick. + */ +static int dm_test_usb_flash(struct unit_test_state *uts) +{ + struct udevice *dev; + struct blk_desc *dev_desc; + char cmp[1024]; + + state_set_skip_delays(true); + ut_assertok(usb_init()); + ut_assertok(uclass_get_device(UCLASS_MASS_STORAGE, 0, &dev)); + ut_assertok(blk_get_device_by_str("usb", "0", &dev_desc)); + + /* Read a few blocks and look for the string we expect */ + ut_asserteq(512, dev_desc->blksz); + memset(cmp, '\0', sizeof(cmp)); + ut_asserteq(2, blk_dread(dev_desc, 0, 2, cmp)); + ut_assertok(strcmp(cmp, "this is a test")); + ut_assertok(usb_stop()); + + return 0; +} +DM_TEST(dm_test_usb_flash, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); + +/* test that we can handle multiple storage devices */ +static int dm_test_usb_multi(struct unit_test_state *uts) +{ + struct udevice *dev; + + state_set_skip_delays(true); + ut_assertok(usb_init()); + ut_assertok(uclass_get_device(UCLASS_MASS_STORAGE, 0, &dev)); + ut_assertok(uclass_get_device(UCLASS_MASS_STORAGE, 1, &dev)); + ut_assertok(uclass_get_device(UCLASS_MASS_STORAGE, 2, &dev)); + ut_assertok(usb_stop()); + + return 0; +} +DM_TEST(dm_test_usb_multi, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); + +/* test that we have an associated ofnode with the usb device */ +static int dm_test_usb_fdt_node(struct unit_test_state *uts) +{ + struct udevice *dev; + ofnode node; + + state_set_skip_delays(true); + ut_assertok(usb_init()); + ut_assertok(uclass_get_device(UCLASS_MASS_STORAGE, 0, &dev)); + node = ofnode_path("/usb@1/hub/usbstor@1"); + ut_asserteq(1, ofnode_equal(node, dev_ofnode(dev))); + ut_assertok(uclass_get_device(UCLASS_MASS_STORAGE, 1, &dev)); + ut_asserteq(1, ofnode_equal(ofnode_null(), dev_ofnode(dev))); + ut_assertok(uclass_get_device(UCLASS_MASS_STORAGE, 2, &dev)); + node = ofnode_path("/usb@1/hub/usbstor@3"); + ut_asserteq(1, ofnode_equal(node, dev_ofnode(dev))); + ut_assertok(usb_stop()); + + return 0; +} +DM_TEST(dm_test_usb_fdt_node, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); + +static int count_usb_devices(void) +{ + struct udevice *hub; + struct uclass *uc; + int count = 0; + int ret; + + ret = uclass_get(UCLASS_USB_HUB, &uc); + if (ret) + return ret; + + uclass_foreach_dev(hub, uc) { + struct udevice *dev; + + count++; + for (device_find_first_child(hub, &dev); + dev; + device_find_next_child(&dev)) { + count++; + } + } + + return count; +} + +/* test that no USB devices are found after we stop the stack */ +static int dm_test_usb_stop(struct unit_test_state *uts) +{ + struct udevice *dev; + + /* Scan and check that all devices are present */ + state_set_skip_delays(true); + ut_assertok(usb_init()); + ut_assertok(uclass_get_device(UCLASS_MASS_STORAGE, 0, &dev)); + ut_assertok(uclass_get_device(UCLASS_MASS_STORAGE, 1, &dev)); + ut_assertok(uclass_get_device(UCLASS_MASS_STORAGE, 2, &dev)); + ut_asserteq(6, count_usb_devices()); + ut_assertok(usb_stop()); + ut_asserteq(0, count_usb_devices()); + + return 0; +} +DM_TEST(dm_test_usb_stop, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); + +/** + * dm_test_usb_keyb() - test USB keyboard driver + * + * This test copies USB keyboard scan codes into the key buffer of the USB + * keyboard emulation driver. These are picked up during emulated interrupts + * by the USB keyboard driver and converted to characters and escape sequences. + * The test then reads and verifies these characters and escape sequences from + * the standard input. + * + * TODO: The following features are not yet tested: + * + * * LED status + * * caps-lock + * * num-lock + * * numerical pad keys + * + * TODO: The following features are not yet implemented by the USB keyboard + * driver and therefore not tested: + * + * * modifiers for non-alpha-numeric keys, e.g. <SHIFT><TAB> and <ALT><F4> + * * some special keys, e.g. <PRINT> + * * some modifiers, e.g. <ALT> and <META> + * * alternative keyboard layouts + * + * @uts: unit test state + * Return: 0 on success + */ +static int dm_test_usb_keyb(struct unit_test_state *uts) +{ + struct udevice *dev; + const struct keyboard_test_data *pos; + const struct keyboard_test_data kbd_test_data[] = { + /* <A> */ + {0x00, 0x04, "a"}, + /* <B> */ + {0x00, 0x05, "b"}, + /* <C> */ + {0x00, 0x06, "c"}, + /* <D> */ + {0x00, 0x07, "d"}, + /* <E> */ + {0x00, 0x08, "e"}, + /* <F> */ + {0x00, 0x09, "f"}, + /* <G> */ + {0x00, 0x0a, "g"}, + /* <H> */ + {0x00, 0x0b, "h"}, + /* <I> */ + {0x00, 0x0c, "i"}, + /* <J> */ + {0x00, 0x0d, "j"}, + /* <K> */ + {0x00, 0x0e, "k"}, + /* <L> */ + {0x00, 0x0f, "l"}, + /* <M> */ + {0x00, 0x10, "m"}, + /* <N> */ + {0x00, 0x11, "n"}, + /* <O> */ + {0x00, 0x12, "o"}, + /* <P> */ + {0x00, 0x13, "p"}, + /* <Q> */ + {0x00, 0x14, "q"}, + /* <R> */ + {0x00, 0x15, "r"}, + /* <S> */ + {0x00, 0x16, "s"}, + /* <T> */ + {0x00, 0x17, "t"}, + /* <U> */ + {0x00, 0x18, "u"}, + /* <V> */ + {0x00, 0x19, "v"}, + /* <W> */ + {0x00, 0x1a, "w"}, + /* <X> */ + {0x00, 0x1b, "x"}, + /* <Y> */ + {0x00, 0x1c, "y"}, + /* <Z> */ + {0x00, 0x1d, "z"}, + + /* <LEFT-SHIFT><A> */ + {0x02, 0x04, "A"}, + /* <RIGHT-SHIFT><Z> */ + {0x20, 0x1d, "Z"}, + + /* <LEFT-CONTROL><A> */ + {0x01, 0x04, "\x01"}, + /* <RIGHT-CONTROL><Z> */ + {0x10, 0x1d, "\x1a"}, + + /* <1> */ + {0x00, 0x1e, "1"}, + /* <2> */ + {0x00, 0x1f, "2"}, + /* <3> */ + {0x00, 0x20, "3"}, + /* <4> */ + {0x00, 0x21, "4"}, + /* <5> */ + {0x00, 0x22, "5"}, + /* <6> */ + {0x00, 0x23, "6"}, + /* <7> */ + {0x00, 0x24, "7"}, + /* <8> */ + {0x00, 0x25, "8"}, + /* <9> */ + {0x00, 0x26, "9"}, + /* <0> */ + {0x00, 0x27, "0"}, + + /* <LEFT-SHIFT><1> */ + {0x02, 0x1e, "!"}, + /* <RIGHT-SHIFT><2> */ + {0x20, 0x1f, "@"}, + /* <LEFT-SHIFT><3> */ + {0x02, 0x20, "#"}, + /* <RIGHT-SHIFT><4> */ + {0x20, 0x21, "$"}, + /* <LEFT-SHIFT><5> */ + {0x02, 0x22, "%"}, + /* <RIGHT-SHIFT><6> */ + {0x20, 0x23, "^"}, + /* <LEFT-SHIFT><7> */ + {0x02, 0x24, "&"}, + /* <RIGHT-SHIFT><8> */ + {0x20, 0x25, "*"}, + /* <LEFT-SHIFT><9> */ + {0x02, 0x26, "("}, + /* <RIGHT-SHIFT><0> */ + {0x20, 0x27, ")"}, + + /* <ENTER> */ + {0x00, 0x28, "\r"}, + /* <ESCAPE> */ + {0x00, 0x29, "\x1b"}, + /* <BACKSPACE> */ + {0x00, 0x2a, "\x08"}, + /* <TAB> */ + {0x00, 0x2b, "\x09"}, + /* <SPACE> */ + {0x00, 0x2c, " "}, + /* <MINUS> */ + {0x00, 0x2d, "-"}, + /* <EQUAL> */ + {0x00, 0x2e, "="}, + /* <LEFT BRACE> */ + {0x00, 0x2f, "["}, + /* <RIGHT BRACE> */ + {0x00, 0x30, "]"}, + /* <BACKSLASH> */ + {0x00, 0x31, "\\"}, + /* <HASH-TILDE> */ + {0x00, 0x32, "#"}, + /* <SEMICOLON> */ + {0x00, 0x33, ";"}, + /* <APOSTROPHE> */ + {0x00, 0x34, "'"}, + /* <GRAVE> */ + {0x00, 0x35, "`"}, + /* <COMMA> */ + {0x00, 0x36, ","}, + /* <DOT> */ + {0x00, 0x37, "."}, + /* <SLASH> */ + {0x00, 0x38, "/"}, + + /* <LEFT-SHIFT><ENTER> */ + {0x02, 0x28, "\r"}, + /* <RIGHT-SHIFT><ESCAPE> */ + {0x20, 0x29, "\x1b"}, + /* <LEFT-SHIFT><BACKSPACE> */ + {0x02, 0x2a, "\x08"}, + /* <RIGHT-SHIFT><TAB> */ + {0x20, 0x2b, "\x09"}, + /* <LEFT-SHIFT><SPACE> */ + {0x02, 0x2c, " "}, + /* <MINUS> */ + {0x20, 0x2d, "_"}, + /* <LEFT-SHIFT><EQUAL> */ + {0x02, 0x2e, "+"}, + /* <RIGHT-SHIFT><LEFT BRACE> */ + {0x20, 0x2f, "{"}, + /* <LEFT-SHIFT><RIGHT BRACE> */ + {0x02, 0x30, "}"}, + /* <RIGHT-SHIFT><BACKSLASH> */ + {0x20, 0x31, "|"}, + /* <LEFT-SHIFT><HASH-TILDE> */ + {0x02, 0x32, "~"}, + /* <RIGHT-SHIFT><SEMICOLON> */ + {0x20, 0x33, ":"}, + /* <LEFT-SHIFT><APOSTROPHE> */ + {0x02, 0x34, "\""}, + /* <RIGHT-SHIFT><GRAVE> */ + {0x20, 0x35, "~"}, + /* <LEFT-SHIFT><COMMA> */ + {0x02, 0x36, "<"}, + /* <RIGHT-SHIFT><DOT> */ + {0x20, 0x37, ">"}, + /* <LEFT-SHIFT><SLASH> */ + {0x02, 0x38, "?"}, +#ifdef CONFIG_USB_KEYBOARD_FN_KEYS + /* <F1> */ + {0x00, 0x3a, "\x1bOP"}, + /* <F2> */ + {0x00, 0x3b, "\x1bOQ"}, + /* <F3> */ + {0x00, 0x3c, "\x1bOR"}, + /* <F4> */ + {0x00, 0x3d, "\x1bOS"}, + /* <F5> */ + {0x00, 0x3e, "\x1b[15~"}, + /* <F6> */ + {0x00, 0x3f, "\x1b[17~"}, + /* <F7> */ + {0x00, 0x40, "\x1b[18~"}, + /* <F8> */ + {0x00, 0x41, "\x1b[19~"}, + /* <F9> */ + {0x00, 0x42, "\x1b[20~"}, + /* <F10> */ + {0x00, 0x43, "\x1b[21~"}, + /* <F11> */ + {0x00, 0x44, "\x1b[23~"}, + /* <F12> */ + {0x00, 0x45, "\x1b[24~"}, + /* <INSERT> */ + {0x00, 0x49, "\x1b[2~"}, + /* <HOME> */ + {0x00, 0x4a, "\x1b[H"}, + /* <PAGE UP> */ + {0x00, 0x4b, "\x1b[5~"}, + /* <DELETE> */ + {0x00, 0x4c, "\x1b[3~"}, + /* <END> */ + {0x00, 0x4d, "\x1b[F"}, + /* <PAGE DOWN> */ + {0x00, 0x4e, "\x1b[6~"}, + /* <RIGHT> */ + {0x00, 0x4f, "\x1b[C"}, + /* <LEFT> */ + {0x00, 0x50, "\x1b[D"}, + /* <DOWN> */ + {0x00, 0x51, "\x1b[B"}, + /* <UP> */ + {0x00, 0x52, "\x1b[A"}, +#endif /* CONFIG_USB_KEYBOARD_FN_KEYS */ + + /* End of list */ + {0x00, 0x00, "\0"} + }; + + + state_set_skip_delays(true); + ut_assertok(usb_init()); + + /* Initially there should be no characters */ + ut_asserteq(0, tstc()); + + ut_assertok(uclass_get_device_by_name(UCLASS_USB_EMUL, "keyb@3", + &dev)); + + /* + * Add scan codes to the USB keyboard buffer. They should appear as + * corresponding characters and escape sequences in stdin. + */ + for (pos = kbd_test_data; pos->scancode; ++pos) { + const char *c; + char scancodes[USB_KBD_BOOT_REPORT_SIZE] = {0}; + + scancodes[0] = pos->modifiers; + scancodes[2] = pos->scancode; + + ut_assertok(sandbox_usb_keyb_add_string(dev, scancodes)); + + for (c = pos->result; *c; ++c) { + ut_asserteq(1, tstc()); + ut_asserteq(*c, getchar()); + } + ut_asserteq(0, tstc()); + } + ut_assertok(usb_stop()); + + return 0; +} +DM_TEST(dm_test_usb_keyb, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); diff --git a/roms/u-boot/test/dm/video.c b/roms/u-boot/test/dm/video.c new file mode 100644 index 000000000..da0ae3622 --- /dev/null +++ b/roms/u-boot/test/dm/video.c @@ -0,0 +1,393 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (c) 2014 Google, Inc + * Written by Simon Glass <sjg@chromium.org> + */ + +#include <common.h> +#include <bzlib.h> +#include <dm.h> +#include <log.h> +#include <malloc.h> +#include <mapmem.h> +#include <os.h> +#include <video.h> +#include <video_console.h> +#include <dm/test.h> +#include <dm/uclass-internal.h> +#include <test/test.h> +#include <test/ut.h> + +/* + * These tests use the standard sandbox frame buffer, the resolution of which + * is defined in the device tree. This only supports 16bpp so the tests only + * test that code path. It would be possible to adjust this fairly easily, + * by adjusting the bpix value in struct sandbox_sdl_plat. However the code + * in sandbox_sdl_sync() would also need to change to handle the different + * surface depth. + */ +/* Basic test of the video uclass */ +static int dm_test_video_base(struct unit_test_state *uts) +{ + struct video_priv *priv; + struct udevice *dev; + + ut_assertok(uclass_get_device(UCLASS_VIDEO, 0, &dev)); + ut_asserteq(1366, video_get_xsize(dev)); + ut_asserteq(768, video_get_ysize(dev)); + priv = dev_get_uclass_priv(dev); + ut_asserteq(priv->fb_size, 1366 * 768 * 2); + + return 0; +} +DM_TEST(dm_test_video_base, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); + +/** + * compress_frame_buffer() - Compress the frame buffer and return its size + * + * We want to write tests which perform operations on the video console and + * check that the frame buffer ends up with the correct contents. But it is + * painful to store 'known good' images for comparison with the frame + * buffer. As an alternative, we can compress the frame buffer and check the + * size of the compressed data. This provides a pretty good level of + * certainty and the resulting tests need only check a single value. + * + * If the copy framebuffer is enabled, this compares it to the main framebuffer + * too. + * + * @uts: Test state + * @dev: Video device + * @return compressed size of the frame buffer, or -ve on error + */ +static int compress_frame_buffer(struct unit_test_state *uts, + struct udevice *dev) +{ + struct video_priv *priv = dev_get_uclass_priv(dev); + struct video_priv *uc_priv = dev_get_uclass_priv(dev); + uint destlen; + void *dest; + int ret; + + destlen = priv->fb_size; + dest = malloc(priv->fb_size); + if (!dest) + return -ENOMEM; + ret = BZ2_bzBuffToBuffCompress(dest, &destlen, + priv->fb, priv->fb_size, + 3, 0, 0); + free(dest); + if (ret) + return ret; + + /* Check here that the copy frame buffer is working correctly */ + if (IS_ENABLED(CONFIG_VIDEO_COPY)) { + ut_assertf(!memcmp(uc_priv->fb, uc_priv->copy_fb, + uc_priv->fb_size), + "Copy framebuffer does not match fb"); + } + + return destlen; +} + +/* + * Call this function at any point to halt and show the current display. Be + * sure to run the test with the -l flag. + */ +static void __maybe_unused see_output(void) +{ + video_sync_all(); + while (1); +} + +/* Select the video console driver to use for a video device */ +static int select_vidconsole(struct unit_test_state *uts, const char *drv_name) +{ + struct sandbox_sdl_plat *plat; + struct udevice *dev; + + ut_assertok(uclass_find_device(UCLASS_VIDEO, 0, &dev)); + ut_assert(!device_active(dev)); + plat = dev_get_plat(dev); + plat->vidconsole_drv_name = "vidconsole0"; + + return 0; +} + +/* Test text output works on the video console */ +static int dm_test_video_text(struct unit_test_state *uts) +{ + struct udevice *dev, *con; + int i; + +#define WHITE 0xffff +#define SCROLL_LINES 100 + + ut_assertok(select_vidconsole(uts, "vidconsole0")); + ut_assertok(uclass_get_device(UCLASS_VIDEO, 0, &dev)); + ut_asserteq(46, compress_frame_buffer(uts, dev)); + + ut_assertok(uclass_get_device(UCLASS_VIDEO_CONSOLE, 0, &con)); + vidconsole_putc_xy(con, 0, 0, 'a'); + ut_asserteq(79, compress_frame_buffer(uts, dev)); + + vidconsole_putc_xy(con, 0, 0, ' '); + ut_asserteq(46, compress_frame_buffer(uts, dev)); + + for (i = 0; i < 20; i++) + vidconsole_putc_xy(con, VID_TO_POS(i * 8), 0, ' ' + i); + ut_asserteq(273, compress_frame_buffer(uts, dev)); + + vidconsole_set_row(con, 0, WHITE); + ut_asserteq(46, compress_frame_buffer(uts, dev)); + + for (i = 0; i < 20; i++) + vidconsole_putc_xy(con, VID_TO_POS(i * 8), 0, ' ' + i); + ut_asserteq(273, compress_frame_buffer(uts, dev)); + + return 0; +} +DM_TEST(dm_test_video_text, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); + +/* Test handling of special characters in the console */ +static int dm_test_video_chars(struct unit_test_state *uts) +{ + struct udevice *dev, *con; + const char *test_string = "Well\b\b\b\bxhe is\r \n\ta very \amodest \bman\n\t\tand Has much to\b\bto be modest about."; + + ut_assertok(select_vidconsole(uts, "vidconsole0")); + ut_assertok(uclass_get_device(UCLASS_VIDEO, 0, &dev)); + ut_assertok(uclass_get_device(UCLASS_VIDEO_CONSOLE, 0, &con)); + vidconsole_put_string(con, test_string); + ut_asserteq(466, compress_frame_buffer(uts, dev)); + + return 0; +} +DM_TEST(dm_test_video_chars, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); + +#ifdef CONFIG_VIDEO_ANSI +#define ANSI_ESC "\x1b" +/* Test handling of ANSI escape sequences */ +static int dm_test_video_ansi(struct unit_test_state *uts) +{ + struct udevice *dev, *con; + + ut_assertok(select_vidconsole(uts, "vidconsole0")); + ut_assertok(uclass_get_device(UCLASS_VIDEO, 0, &dev)); + ut_assertok(uclass_get_device(UCLASS_VIDEO_CONSOLE, 0, &con)); + + /* reference clear: */ + video_clear(con->parent); + video_sync(con->parent, false); + ut_asserteq(46, compress_frame_buffer(uts, dev)); + + /* test clear escape sequence: [2J */ + vidconsole_put_string(con, "A\tB\tC"ANSI_ESC"[2J"); + ut_asserteq(46, compress_frame_buffer(uts, dev)); + + /* test set-cursor: [%d;%df */ + vidconsole_put_string(con, "abc"ANSI_ESC"[2;2fab"ANSI_ESC"[4;4fcd"); + ut_asserteq(143, compress_frame_buffer(uts, dev)); + + /* test colors (30-37 fg color, 40-47 bg color) */ + vidconsole_put_string(con, ANSI_ESC"[30;41mfoo"); /* black on red */ + vidconsole_put_string(con, ANSI_ESC"[33;44mbar"); /* yellow on blue */ + ut_asserteq(272, compress_frame_buffer(uts, dev)); + + return 0; +} +DM_TEST(dm_test_video_ansi, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); +#endif + +/** + * check_vidconsole_output() - Run a text console test + * + * @uts: Test state + * @rot: Console rotation (0=normal orientation, 1=90 degrees clockwise, + * 2=upside down, 3=90 degree counterclockwise) + * @wrap_size: Expected size of compressed frame buffer for the wrap test + * @scroll_size: Same for the scroll test + * @return 0 on success + */ +static int check_vidconsole_output(struct unit_test_state *uts, int rot, + int wrap_size, int scroll_size) +{ + struct udevice *dev, *con; + struct sandbox_sdl_plat *plat; + int i; + + ut_assertok(uclass_find_device(UCLASS_VIDEO, 0, &dev)); + ut_assert(!device_active(dev)); + plat = dev_get_plat(dev); + plat->rot = rot; + + ut_assertok(uclass_get_device(UCLASS_VIDEO, 0, &dev)); + ut_assertok(uclass_get_device(UCLASS_VIDEO_CONSOLE, 0, &con)); + ut_asserteq(46, compress_frame_buffer(uts, dev)); + + /* Check display wrap */ + for (i = 0; i < 120; i++) + vidconsole_put_char(con, 'A' + i % 50); + ut_asserteq(wrap_size, compress_frame_buffer(uts, dev)); + + /* Check display scrolling */ + for (i = 0; i < SCROLL_LINES; i++) { + vidconsole_put_char(con, 'A' + i % 50); + vidconsole_put_char(con, '\n'); + } + ut_asserteq(scroll_size, compress_frame_buffer(uts, dev)); + + /* If we scroll enough, the screen becomes blank again */ + for (i = 0; i < SCROLL_LINES; i++) + vidconsole_put_char(con, '\n'); + ut_asserteq(46, compress_frame_buffer(uts, dev)); + + return 0; +} + +/* Test text output through the console uclass */ +static int dm_test_video_context(struct unit_test_state *uts) +{ + ut_assertok(select_vidconsole(uts, "vidconsole0")); + ut_assertok(check_vidconsole_output(uts, 0, 788, 453)); + + return 0; +} +DM_TEST(dm_test_video_context, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); + +/* Test rotated text output through the console uclass */ +static int dm_test_video_rotation1(struct unit_test_state *uts) +{ + ut_assertok(check_vidconsole_output(uts, 1, 1112, 680)); + + return 0; +} +DM_TEST(dm_test_video_rotation1, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); + +/* Test rotated text output through the console uclass */ +static int dm_test_video_rotation2(struct unit_test_state *uts) +{ + ut_assertok(check_vidconsole_output(uts, 2, 783, 445)); + + return 0; +} +DM_TEST(dm_test_video_rotation2, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); + +/* Test rotated text output through the console uclass */ +static int dm_test_video_rotation3(struct unit_test_state *uts) +{ + ut_assertok(check_vidconsole_output(uts, 3, 1134, 681)); + + return 0; +} +DM_TEST(dm_test_video_rotation3, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); + +/* Read a file into memory and return a pointer to it */ +static int read_file(struct unit_test_state *uts, const char *fname, + ulong *addrp) +{ + int buf_size = 100000; + ulong addr = 0; + int size, fd; + char *buf; + + buf = map_sysmem(addr, 0); + ut_assert(buf != NULL); + fd = os_open(fname, OS_O_RDONLY); + ut_assert(fd >= 0); + size = os_read(fd, buf, buf_size); + os_close(fd); + ut_assert(size >= 0); + ut_assert(size < buf_size); + *addrp = addr; + + return 0; +} + +/* Test drawing a bitmap file */ +static int dm_test_video_bmp(struct unit_test_state *uts) +{ + struct udevice *dev; + ulong addr; + + ut_assertok(uclass_get_device(UCLASS_VIDEO, 0, &dev)); + ut_assertok(read_file(uts, "tools/logos/denx.bmp", &addr)); + + ut_assertok(video_bmp_display(dev, addr, 0, 0, false)); + ut_asserteq(1368, compress_frame_buffer(uts, dev)); + + return 0; +} +DM_TEST(dm_test_video_bmp, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); + +/* Test drawing a compressed bitmap file */ +static int dm_test_video_bmp_comp(struct unit_test_state *uts) +{ + struct udevice *dev; + ulong addr; + + ut_assertok(uclass_get_device(UCLASS_VIDEO, 0, &dev)); + ut_assertok(read_file(uts, "tools/logos/denx-comp.bmp", &addr)); + + ut_assertok(video_bmp_display(dev, addr, 0, 0, false)); + ut_asserteq(1368, compress_frame_buffer(uts, dev)); + + return 0; +} +DM_TEST(dm_test_video_bmp_comp, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); + +/* Test TrueType console */ +static int dm_test_video_truetype(struct unit_test_state *uts) +{ + struct udevice *dev, *con; + const char *test_string = "Criticism may not be agreeable, but it is necessary. It fulfils the same function as pain in the human body. It calls attention to an unhealthy state of things. Some see private enterprise as a predatory target to be shot, others as a cow to be milked, but few are those who see it as a sturdy horse pulling the wagon. The \aprice OF\b\bof greatness\n\tis responsibility.\n\nBye"; + + ut_assertok(uclass_get_device(UCLASS_VIDEO, 0, &dev)); + ut_assertok(uclass_get_device(UCLASS_VIDEO_CONSOLE, 0, &con)); + vidconsole_put_string(con, test_string); + ut_asserteq(12237, compress_frame_buffer(uts, dev)); + + return 0; +} +DM_TEST(dm_test_video_truetype, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); + +/* Test scrolling TrueType console */ +static int dm_test_video_truetype_scroll(struct unit_test_state *uts) +{ + struct sandbox_sdl_plat *plat; + struct udevice *dev, *con; + const char *test_string = "Criticism may not be agreeable, but it is necessary. It fulfils the same function as pain in the human body. It calls attention to an unhealthy state of things. Some see private enterprise as a predatory target to be shot, others as a cow to be milked, but few are those who see it as a sturdy horse pulling the wagon. The \aprice OF\b\bof greatness\n\tis responsibility.\n\nBye"; + + ut_assertok(uclass_find_device(UCLASS_VIDEO, 0, &dev)); + ut_assert(!device_active(dev)); + plat = dev_get_plat(dev); + plat->font_size = 100; + + ut_assertok(uclass_get_device(UCLASS_VIDEO, 0, &dev)); + ut_assertok(uclass_get_device(UCLASS_VIDEO_CONSOLE, 0, &con)); + vidconsole_put_string(con, test_string); + ut_asserteq(35030, compress_frame_buffer(uts, dev)); + + return 0; +} +DM_TEST(dm_test_video_truetype_scroll, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); + +/* Test TrueType backspace, within and across lines */ +static int dm_test_video_truetype_bs(struct unit_test_state *uts) +{ + struct sandbox_sdl_plat *plat; + struct udevice *dev, *con; + const char *test_string = "...Criticism may or may\b\b\b\b\b\bnot be agreeable, but seldom it is necessary\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\bit is necessary. It fulfils the same function as pain in the human body. It calls attention to an unhealthy state of things."; + + ut_assertok(uclass_find_device(UCLASS_VIDEO, 0, &dev)); + ut_assert(!device_active(dev)); + plat = dev_get_plat(dev); + plat->font_size = 100; + + ut_assertok(uclass_get_device(UCLASS_VIDEO, 0, &dev)); + ut_assertok(uclass_get_device(UCLASS_VIDEO_CONSOLE, 0, &con)); + vidconsole_put_string(con, test_string); + ut_asserteq(29018, compress_frame_buffer(uts, dev)); + + return 0; +} +DM_TEST(dm_test_video_truetype_bs, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); diff --git a/roms/u-boot/test/dm/virtio.c b/roms/u-boot/test/dm/virtio.c new file mode 100644 index 000000000..9a7e658cc --- /dev/null +++ b/roms/u-boot/test/dm/virtio.c @@ -0,0 +1,132 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2018, Bin Meng <bmeng.cn@gmail.com> + */ + +#include <common.h> +#include <dm.h> +#include <virtio_types.h> +#include <virtio.h> +#include <virtio_ring.h> +#include <dm/device-internal.h> +#include <dm/root.h> +#include <dm/test.h> +#include <dm/uclass-internal.h> +#include <test/test.h> +#include <test/ut.h> + +/* Basic test of the virtio uclass */ +static int dm_test_virtio_base(struct unit_test_state *uts) +{ + struct udevice *bus, *dev; + u8 status; + + /* check probe success */ + ut_assertok(uclass_first_device(UCLASS_VIRTIO, &bus)); + ut_assertnonnull(bus); + + /* check the child virtio-blk device is bound */ + ut_assertok(device_find_first_child(bus, &dev)); + ut_assertnonnull(dev); + ut_assertok(strcmp(dev->name, "virtio-blk#0")); + + /* check driver status */ + ut_assertok(virtio_get_status(dev, &status)); + ut_asserteq(VIRTIO_CONFIG_S_ACKNOWLEDGE, status); + + return 0; +} +DM_TEST(dm_test_virtio_base, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); + +/* Test all of the virtio uclass ops */ +static int dm_test_virtio_all_ops(struct unit_test_state *uts) +{ + struct udevice *bus, *dev; + struct virtio_dev_priv *uc_priv; + uint offset = 0, len = 0, nvqs = 1; + void *buffer = NULL; + u8 status; + u32 counter; + u64 features; + struct virtqueue *vqs[2]; + + /* check probe success */ + ut_assertok(uclass_first_device(UCLASS_VIRTIO, &bus)); + ut_assertnonnull(bus); + + /* check the child virtio-blk device is bound */ + ut_assertok(device_find_first_child(bus, &dev)); + ut_assertnonnull(dev); + + /* + * fake the virtio device probe by filling in uc_priv->vdev + * which is used by virtio_find_vqs/virtio_del_vqs. + */ + uc_priv = dev_get_uclass_priv(bus); + ut_assertnonnull(uc_priv); + uc_priv->vdev = dev; + + /* test virtio_xxx APIs */ + ut_assertok(virtio_get_config(dev, offset, buffer, len)); + ut_assertok(virtio_set_config(dev, offset, buffer, len)); + ut_asserteq(-ENOSYS, virtio_generation(dev, &counter)); + ut_assertok(virtio_set_status(dev, VIRTIO_CONFIG_S_DRIVER_OK)); + ut_assertok(virtio_get_status(dev, &status)); + ut_asserteq(VIRTIO_CONFIG_S_DRIVER_OK, status); + ut_assertok(virtio_reset(dev)); + ut_assertok(virtio_get_status(dev, &status)); + ut_asserteq(0, status); + ut_assertok(virtio_get_features(dev, &features)); + ut_asserteq(VIRTIO_F_VERSION_1, features); + ut_assertok(virtio_set_features(dev)); + ut_assertok(virtio_find_vqs(dev, nvqs, vqs)); + ut_assertok(virtio_del_vqs(dev)); + ut_assertok(virtio_notify(dev, vqs[0])); + + return 0; +} +DM_TEST(dm_test_virtio_all_ops, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); + +/* Test of the virtio driver that does not have required driver ops */ +static int dm_test_virtio_missing_ops(struct unit_test_state *uts) +{ + struct udevice *bus; + + /* find the virtio device */ + ut_assertok(uclass_find_device(UCLASS_VIRTIO, 1, &bus)); + + /* + * Probe the device should fail with error -ENOENT. + * See ops check in virtio_uclass_pre_probe(). + */ + ut_asserteq(-ENOENT, device_probe(bus)); + + return 0; +} +DM_TEST(dm_test_virtio_missing_ops, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); + +/* Test removal of virtio device driver */ +static int dm_test_virtio_remove(struct unit_test_state *uts) +{ + struct udevice *bus, *dev; + + /* check probe success */ + ut_assertok(uclass_first_device(UCLASS_VIRTIO, &bus)); + ut_assertnonnull(bus); + + /* check the child virtio-blk device is bound */ + ut_assertok(device_find_first_child(bus, &dev)); + ut_assertnonnull(dev); + + /* set driver status to VIRTIO_CONFIG_S_DRIVER_OK */ + ut_assertok(virtio_set_status(dev, VIRTIO_CONFIG_S_DRIVER_OK)); + + /* check the device can be successfully removed */ + dev_or_flags(dev, DM_FLAG_ACTIVATED); + ut_asserteq(-EKEYREJECTED, device_remove(bus, DM_REMOVE_ACTIVE_ALL)); + + ut_asserteq(false, device_active(dev)); + + return 0; +} +DM_TEST(dm_test_virtio_remove, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); diff --git a/roms/u-boot/test/dm/wdt.c b/roms/u-boot/test/dm/wdt.c new file mode 100644 index 000000000..24b991dff --- /dev/null +++ b/roms/u-boot/test/dm/wdt.c @@ -0,0 +1,41 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright 2017 Google, Inc + */ + +#include <common.h> +#include <dm.h> +#include <wdt.h> +#include <asm/state.h> +#include <asm/test.h> +#include <dm/test.h> +#include <test/test.h> +#include <test/ut.h> + +/* Test that watchdog driver functions are called */ +static int dm_test_wdt_base(struct unit_test_state *uts) +{ + struct sandbox_state *state = state_get_current(); + struct udevice *dev; + const u64 timeout = 42; + + ut_assertok(uclass_get_device(UCLASS_WDT, 0, &dev)); + ut_assertnonnull(dev); + ut_asserteq(0, state->wdt.counter); + ut_asserteq(false, state->wdt.running); + + ut_assertok(wdt_start(dev, timeout, 0)); + ut_asserteq(timeout, state->wdt.counter); + ut_asserteq(true, state->wdt.running); + + uint reset_count = state->wdt.reset_count; + ut_assertok(wdt_reset(dev)); + ut_asserteq(reset_count + 1, state->wdt.reset_count); + ut_asserteq(true, state->wdt.running); + + ut_assertok(wdt_stop(dev)); + ut_asserteq(false, state->wdt.running); + + return 0; +} +DM_TEST(dm_test_wdt_base, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); |