blob: 40af1ecf5e9a7cb86631c7f7c93a192bf215a4b5 [file]
/* Copyright 2021 Google LLC
* SPDX-License-Identifier: Apache-2.0
*/
#include <zephyr/device.h>
#include <zephyr/devicetree.h>
#include <zephyr/drivers/syscon.h>
#include <zephyr/ztest.h>
#include <zephyr/linker/devicetree_regions.h>
#define RES_SECT LINKER_DT_NODE_REGION_NAME(DT_NODELABEL(res))
uint8_t var_in_res0[DT_REG_SIZE(DT_NODELABEL(res))] __attribute((__section__(RES_SECT)));
ZTEST(syscon, test_size)
{
const struct device *const dev = DEVICE_DT_GET(DT_NODELABEL(syscon));
const size_t expected_size = DT_REG_SIZE(DT_NODELABEL(syscon));
size_t size;
zassert_ok(syscon_get_size(dev, &size));
zassert_equal(size, expected_size, "size(%zu) != expected_size(%zu)", size,
expected_size);
}
ZTEST(syscon, test_out_of_bounds)
{
const struct device *const dev = DEVICE_DT_GET(DT_NODELABEL(syscon));
uint32_t val;
zassert_equal(syscon_read_reg(dev, DT_REG_SIZE(DT_NODELABEL(syscon)), &val), -EINVAL);
zassert_equal(syscon_write_reg(dev, DT_REG_SIZE(DT_NODELABEL(syscon)), val), -EINVAL);
}
ZTEST(syscon, test_read)
{
const struct device *const dev = DEVICE_DT_GET(DT_NODELABEL(syscon));
uintptr_t base_addr;
uint32_t val;
zassert_ok(syscon_get_base(dev, &base_addr));
for (size_t i = 0; i < DT_REG_SIZE(DT_NODELABEL(syscon)); ++i) {
((uint8_t *)base_addr)[i] = i;
zassert_ok(syscon_read_reg(dev, i, &val));
zassert_equal(i, val);
}
}
ZTEST(syscon, test_write)
{
const struct device *const dev = DEVICE_DT_GET(DT_NODELABEL(syscon));
uintptr_t base_addr;
zassert_ok(syscon_get_base(dev, &base_addr));
for (uint32_t i = 0; i < DT_REG_SIZE(DT_NODELABEL(syscon)); ++i) {
zassert_ok(syscon_write_reg(dev, i, i));
zassert_equal(((uint8_t *)base_addr)[i], i);
}
}
ZTEST(syscon, test_update_bits)
{
const struct device *const dev = DEVICE_DT_GET(DT_NODELABEL(syscon));
uintptr_t base_addr;
uint32_t val;
zassert_ok(syscon_get_base(dev, &base_addr));
/* Write a known value, then update specific bits */
zassert_ok(syscon_write_reg(dev, 0, 0xA5));
zassert_ok(syscon_update_bits(dev, 0, 0x0F, 0x03));
zassert_ok(syscon_read_reg(dev, 0, &val));
zassert_equal(val, 0xA3, "expected 0xA3, got 0x%02x", val);
/* Update with mask that covers all bits */
zassert_ok(syscon_update_bits(dev, 0, 0xFF, 0x42));
zassert_ok(syscon_read_reg(dev, 0, &val));
zassert_equal(val, 0x42);
/* Update with zero mask changes nothing */
zassert_ok(syscon_update_bits(dev, 0, 0x00, 0xFF));
zassert_ok(syscon_read_reg(dev, 0, &val));
zassert_equal(val, 0x42);
}
ZTEST(syscon, test_update_bits_out_of_bounds)
{
const struct device *const dev = DEVICE_DT_GET(DT_NODELABEL(syscon));
zassert_equal(syscon_update_bits(dev, DT_REG_SIZE(DT_NODELABEL(syscon)), 0xFF, 0x00),
-EINVAL);
}
ZTEST(syscon, test_misaligned_access)
{
const struct device *const dev32 = DEVICE_DT_GET(DT_NODELABEL(syscon32));
uint32_t val;
/* Aligned access should succeed */
zassert_ok(syscon_write_reg(dev32, 0, 0xDEADBEEF));
zassert_ok(syscon_read_reg(dev32, 0, &val));
zassert_equal(val, 0xDEADBEEF);
zassert_ok(syscon_write_reg(dev32, 4, 0xCAFEBABE));
zassert_ok(syscon_read_reg(dev32, 4, &val));
zassert_equal(val, 0xCAFEBABE);
/* Misaligned accesses should be rejected */
zassert_equal(syscon_read_reg(dev32, 1, &val), -EINVAL);
zassert_equal(syscon_read_reg(dev32, 2, &val), -EINVAL);
zassert_equal(syscon_read_reg(dev32, 3, &val), -EINVAL);
zassert_equal(syscon_write_reg(dev32, 1, 0), -EINVAL);
zassert_equal(syscon_write_reg(dev32, 5, 0), -EINVAL);
zassert_equal(syscon_update_bits(dev32, 3, 0xFF, 0), -EINVAL);
}
ZTEST_SUITE(syscon, NULL, NULL, NULL, NULL, NULL);