device_pm_control_nop is now deprecated in favour of NULL. Signed-off-by: Gerard Marull-Paretas <gerard.marull@nordicsemi.no>
274 lines
8.1 KiB
C
274 lines
8.1 KiB
C
/*
|
|
* Copyright (c) 2020 Intel Corporation
|
|
*
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
|
|
#include <ztest.h>
|
|
#include <device.h>
|
|
|
|
#define DT_DRV_COMPAT fakedriver
|
|
|
|
/*
|
|
* Driver with a single MMIO region to manage
|
|
*/
|
|
|
|
struct foo_single_dev_data {
|
|
DEVICE_MMIO_RAM;
|
|
int baz;
|
|
};
|
|
|
|
struct foo_single_dev_data foo0_data;
|
|
|
|
struct foo_single_config_info {
|
|
DEVICE_MMIO_ROM;
|
|
};
|
|
|
|
const struct foo_single_config_info foo0_config = {
|
|
DEVICE_MMIO_ROM_INIT(DT_DRV_INST(0)),
|
|
};
|
|
|
|
int foo_single_init(const struct device *dev)
|
|
{
|
|
DEVICE_MMIO_MAP(dev, K_MEM_CACHE_NONE);
|
|
|
|
return 0;
|
|
}
|
|
|
|
/* fake API pointer, we don't use it at all for this suite */
|
|
DEVICE_DEFINE(foo0, "foo0", foo_single_init, NULL,
|
|
&foo0_data, &foo0_config,
|
|
POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT,
|
|
(void *)0xDEADBEEF);
|
|
|
|
/**
|
|
* @brief Test DEVICE_MMIO_* macros
|
|
*
|
|
* We show that we can make mapping calls and that the address returned by
|
|
* DEVICE_MMIO_GET() is not NULL, indicating that the kernel mapped
|
|
* stuff somewhere.
|
|
*
|
|
* We also perform some checks depending on configuration:
|
|
* - If MMIO addresses are maintained in RAM, check that the ROM struct
|
|
* was populated correctly.
|
|
* - If MMIO addresses are maintained in ROM, check that the DTS info,
|
|
* the ROM region, and the result of DEVICE_MMIO_GET() all
|
|
* point to the same address. We show that no extra memory is used in
|
|
* dev_data.
|
|
*
|
|
* @ingroup kernel_device_tests
|
|
*/
|
|
void test_mmio_single(void)
|
|
{
|
|
struct z_device_mmio_rom *rom;
|
|
const struct device *dev = device_get_binding("foo0");
|
|
mm_reg_t regs;
|
|
|
|
zassert_not_null(dev, "null foo0");
|
|
|
|
regs = DEVICE_MMIO_GET(dev);
|
|
rom = DEVICE_MMIO_ROM_PTR(dev);
|
|
|
|
/* A sign that something didn't get initialized, shouldn't ever
|
|
* be 0
|
|
*/
|
|
zassert_not_equal(regs, 0, "NULL regs");
|
|
|
|
#ifdef DEVICE_MMIO_IS_IN_RAM
|
|
/* The config info should just contain the addr/size from DTS.
|
|
* The best we can check with 'regs' is that it's nonzero, as if
|
|
* an MMU is enabled, the kernel chooses the virtual address to
|
|
* place it at. We don't otherwise look at `regs`; other tests will
|
|
* prove that k_map() actually works.
|
|
*/
|
|
zassert_equal(rom->phys_addr, DT_INST_REG_ADDR(0), "bad phys_addr");
|
|
zassert_equal(rom->size, DT_INST_REG_SIZE(0), "bad size");
|
|
#else
|
|
/* Config info contains base address, which should be the base
|
|
* address from DTS, and regs should have the same value.
|
|
* In this configuration dev_data has nothing mmio-related in it
|
|
*/
|
|
zassert_equal(rom->addr, DT_INST_REG_ADDR(0), "bad addr");
|
|
zassert_equal(regs, rom->addr, "bad regs");
|
|
/* Just the baz member */
|
|
zassert_equal(sizeof(struct foo_single_dev_data), sizeof(int),
|
|
"too big foo_single_dev_data");
|
|
#endif
|
|
}
|
|
|
|
/*
|
|
* Driver with multiple MMIO regions to manage
|
|
*/
|
|
|
|
struct foo_mult_dev_data {
|
|
int baz;
|
|
|
|
DEVICE_MMIO_NAMED_RAM(courge);
|
|
DEVICE_MMIO_NAMED_RAM(grault);
|
|
};
|
|
|
|
struct foo_mult_dev_data foo12_data;
|
|
|
|
struct foo_mult_config_info {
|
|
DEVICE_MMIO_NAMED_ROM(courge);
|
|
DEVICE_MMIO_NAMED_ROM(grault);
|
|
};
|
|
|
|
const struct foo_mult_config_info foo12_config = {
|
|
DEVICE_MMIO_NAMED_ROM_INIT(courge, DT_DRV_INST(1)),
|
|
DEVICE_MMIO_NAMED_ROM_INIT(grault, DT_DRV_INST(2))
|
|
};
|
|
|
|
#define DEV_DATA(dev) ((struct foo_mult_dev_data *)((dev)->data))
|
|
#define DEV_CFG(dev) ((struct foo_mult_config_info *)((dev)->config))
|
|
|
|
int foo_mult_init(const struct device *dev)
|
|
{
|
|
DEVICE_MMIO_NAMED_MAP(dev, courge, K_MEM_CACHE_NONE);
|
|
DEVICE_MMIO_NAMED_MAP(dev, grault, K_MEM_CACHE_NONE);
|
|
|
|
return 0;
|
|
}
|
|
|
|
DEVICE_DEFINE(foo12, "foo12", foo_mult_init, NULL,
|
|
&foo12_data, &foo12_config,
|
|
POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT,
|
|
(void *)0xDEADBEEF);
|
|
|
|
/**
|
|
* @brief Test DEVICE_MMIO_NAMED_* macros
|
|
*
|
|
* We show that we can make mapping calls and that the address returned by
|
|
* DEVICE_MMIO_NAMED_GET() is not NULL, indicating that the kernel mapped
|
|
* stuff somewhere.
|
|
*
|
|
* We show that this works for a device instance that has two named regions,
|
|
* 'courge' and 'grault' that respectively come from DTS instances 1 and 2.
|
|
*
|
|
* We also perform some checks depending on configuration:
|
|
* - If MMIO addresses are maintained in RAM, check that the ROM struct
|
|
* was populated correctly.
|
|
* - If MMIO addresses are maintained in ROM, check that the DTS info,
|
|
* the ROM region, and the result of DEVICE_MMIO_NAMED_GET() all
|
|
* point to the same address. We show that no extra memory is used in
|
|
* dev_data.
|
|
*
|
|
* @ingroup kernel_device_tests
|
|
*/
|
|
void test_mmio_multiple(void)
|
|
{
|
|
/* See comments for test_mmio_single */
|
|
const struct device *dev = device_get_binding("foo12");
|
|
mm_reg_t regs_courge, regs_grault;
|
|
const struct z_device_mmio_rom *rom_courge, *rom_grault;
|
|
|
|
zassert_not_null(dev, "null foo12");
|
|
|
|
regs_courge = DEVICE_MMIO_NAMED_GET(dev, courge);
|
|
regs_grault = DEVICE_MMIO_NAMED_GET(dev, grault);
|
|
rom_courge = DEVICE_MMIO_NAMED_ROM_PTR(dev, courge);
|
|
rom_grault = DEVICE_MMIO_NAMED_ROM_PTR(dev, grault);
|
|
|
|
zassert_not_equal(regs_courge, 0, "bad regs_courge");
|
|
zassert_not_equal(regs_grault, 0, "bad regs_grault");
|
|
|
|
#ifdef DEVICE_MMIO_IS_IN_RAM
|
|
zassert_equal(rom_courge->phys_addr, DT_INST_REG_ADDR(1),
|
|
"bad phys_addr (courge)");
|
|
zassert_equal(rom_courge->size, DT_INST_REG_SIZE(1),
|
|
"bad size (courge)");
|
|
zassert_equal(rom_grault->phys_addr, DT_INST_REG_ADDR(2),
|
|
"bad phys_addr (grault)");
|
|
zassert_equal(rom_grault->size, DT_INST_REG_SIZE(2),
|
|
"bad size (grault)");
|
|
#else
|
|
zassert_equal(rom_courge->addr, DT_INST_REG_ADDR(1),
|
|
"bad addr (courge)");
|
|
zassert_equal(regs_courge, rom_courge->addr, "bad regs (courge)");
|
|
zassert_equal(rom_grault->addr, DT_INST_REG_ADDR(2),
|
|
"bad addr (grault)");
|
|
zassert_equal(regs_grault, rom_grault->addr, "bad regs (grault)");
|
|
zassert_equal(sizeof(struct foo_mult_dev_data), sizeof(int),
|
|
"too big foo_mult_dev_data");
|
|
#endif
|
|
}
|
|
|
|
/*
|
|
* Not using driver model, toplevel definition
|
|
*/
|
|
DEVICE_MMIO_TOPLEVEL(foo3, DT_DRV_INST(3));
|
|
DEVICE_MMIO_TOPLEVEL_STATIC(foo4, DT_DRV_INST(4));
|
|
|
|
/**
|
|
* @brief Test DEVICE_MMIO_TOPLEVEL_* macros
|
|
*
|
|
* We show that we can make mapping calls and that the address returned by
|
|
* DEVICE_MMIO_TOPLEVEL_GET() is not NULL, indicating that the kernel mapped
|
|
* stuff somewhere.
|
|
*
|
|
* We do this for two different MMIO toplevel instances; one declared
|
|
* statically and one not.
|
|
*
|
|
* We also perform some checks depending on configuration:
|
|
* - If MMIO addresses are maintained in RAM, check that the ROM struct
|
|
* was populated correctly.
|
|
* - If MMIO addresses are maintained in ROM, check that the DTS info,
|
|
* the ROM region, and the result of DEVICE_MMIO_TOPLEVEL_GET() all
|
|
* point to the same address
|
|
*
|
|
* @ingroup kernel_device_tests
|
|
*/
|
|
void test_mmio_toplevel(void)
|
|
{
|
|
mm_reg_t regs_foo3, regs_foo4;
|
|
const struct z_device_mmio_rom *rom_foo3, *rom_foo4;
|
|
|
|
DEVICE_MMIO_TOPLEVEL_MAP(foo3, K_MEM_CACHE_NONE);
|
|
DEVICE_MMIO_TOPLEVEL_MAP(foo4, K_MEM_CACHE_NONE);
|
|
|
|
regs_foo3 = DEVICE_MMIO_TOPLEVEL_GET(foo3);
|
|
regs_foo4 = DEVICE_MMIO_TOPLEVEL_GET(foo4);
|
|
rom_foo3 = DEVICE_MMIO_TOPLEVEL_ROM_PTR(foo3);
|
|
rom_foo4 = DEVICE_MMIO_TOPLEVEL_ROM_PTR(foo4);
|
|
|
|
zassert_not_equal(regs_foo3, 0, "bad regs_courge");
|
|
zassert_not_equal(regs_foo4, 0, "bad regs_grault");
|
|
|
|
#ifdef DEVICE_MMIO_IS_IN_RAM
|
|
zassert_equal(rom_foo3->phys_addr, DT_INST_REG_ADDR(3),
|
|
"bad phys_addr (foo3)");
|
|
zassert_equal(rom_foo3->size, DT_INST_REG_SIZE(3),
|
|
"bad size (foo3)");
|
|
zassert_equal(rom_foo4->phys_addr, DT_INST_REG_ADDR(4),
|
|
"bad phys_addr (foo4)");
|
|
zassert_equal(rom_foo4->size, DT_INST_REG_SIZE(4),
|
|
"bad size (foo4)");
|
|
#else
|
|
zassert_equal(rom_foo3->addr, DT_INST_REG_ADDR(3),
|
|
"bad addr (foo3)");
|
|
zassert_equal(regs_foo3, rom_foo3->addr, "bad regs (foo3)");
|
|
zassert_equal(rom_foo4->addr, DT_INST_REG_ADDR(4),
|
|
"bad addr (foo4)");
|
|
zassert_equal(regs_foo4, rom_foo4->addr, "bad regs (foo4)");
|
|
#endif
|
|
}
|
|
|
|
/**
|
|
* @brief device_map() test
|
|
*
|
|
* Show that device_map() populates a memory address. We don't do anything else;
|
|
* tests for k_map() will prove that virtual memory mapping actually works.
|
|
*/
|
|
void test_mmio_device_map(void)
|
|
{
|
|
#ifdef DEVICE_MMIO_IS_IN_RAM
|
|
mm_reg_t regs = 0;
|
|
|
|
device_map(®s, 0xF0000000, 0x1000, K_MEM_CACHE_NONE);
|
|
|
|
zassert_not_equal(regs, 0, "bad regs");
|
|
#else
|
|
ztest_test_skip();
|
|
#endif
|
|
}
|