blob: 853527b1dde0b58b15d6d039612f999dbd06fd93 [file] [log] [blame]
// Copyright lowRISC contributors.
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0
#include "sw/device/lib/dif/dif_pinmux.h"
#include "gtest/gtest.h"
#include "sw/device/lib/base/mmio.h"
#include "sw/device/lib/base/mock_mmio.h"
#include "sw/device/lib/dif/dif_base.h"
#include "sw/device/lib/dif/dif_test_base.h"
#include "pinmux_regs.h" // Generated.
namespace dif_pinmux_unittest {
namespace {
using mock_mmio::MmioTest;
using mock_mmio::MockDevice;
using testing::Test;
class PinmuxTest : public Test, public MmioTest {
protected:
void SetUp() { ASSERT_DIF_OK(dif_pinmux_init(dev().region(), &dif_pinmux_)); }
dif_pinmux_t dif_pinmux_;
};
TEST_F(PinmuxTest, NullArgs) {
dif_pinmux_index_t index_arg{};
dif_pinmux_lock_target_t lock_arg{};
bool bool_arg{};
EXPECT_DIF_BADARG(dif_pinmux_lock(nullptr, index_arg, lock_arg));
EXPECT_DIF_BADARG(
dif_pinmux_is_locked(nullptr, index_arg, lock_arg, &bool_arg));
EXPECT_DIF_BADARG(
dif_pinmux_is_locked(&dif_pinmux_, index_arg, lock_arg, nullptr));
EXPECT_DIF_BADARG(dif_pinmux_input_select(nullptr, index_arg, index_arg));
EXPECT_DIF_BADARG(dif_pinmux_output_select(nullptr, index_arg, index_arg));
dif_pinmux_pad_attr_t pad_attr_arg{};
dif_pinmux_pad_kind_t pad_kind_arg{};
EXPECT_DIF_BADARG(dif_pinmux_pad_write_attrs(nullptr, index_arg, pad_kind_arg,
pad_attr_arg, &pad_attr_arg));
EXPECT_DIF_BADARG(dif_pinmux_pad_write_attrs(
&dif_pinmux_, index_arg, pad_kind_arg, pad_attr_arg, nullptr));
EXPECT_DIF_BADARG(dif_pinmux_pad_get_attrs(nullptr, index_arg, pad_kind_arg,
&pad_attr_arg));
EXPECT_DIF_BADARG(
dif_pinmux_pad_get_attrs(&dif_pinmux_, index_arg, pad_kind_arg, nullptr));
dif_pinmux_sleep_mode_t sleep_mode_arg{};
EXPECT_DIF_BADARG(dif_pinmux_pad_sleep_enable(nullptr, index_arg,
pad_kind_arg, sleep_mode_arg));
EXPECT_DIF_BADARG(
dif_pinmux_pad_sleep_disable(nullptr, index_arg, pad_kind_arg));
EXPECT_DIF_BADARG(dif_pinmux_pad_sleep_get_state(nullptr, index_arg,
pad_kind_arg, &bool_arg));
EXPECT_DIF_BADARG(dif_pinmux_pad_sleep_get_state(&dif_pinmux_, index_arg,
pad_kind_arg, nullptr));
EXPECT_DIF_BADARG(
dif_pinmux_pad_sleep_clear_state(nullptr, index_arg, pad_kind_arg));
dif_pinmux_wakeup_config_t wakeup_arg{};
EXPECT_DIF_BADARG(
dif_pinmux_wakeup_detector_enable(nullptr, index_arg, wakeup_arg));
EXPECT_DIF_BADARG(dif_pinmux_wakeup_detector_disable(nullptr, index_arg));
EXPECT_DIF_BADARG(dif_pinmux_wakeup_cause_clear(nullptr));
uint32_t uint32_arg{};
EXPECT_DIF_BADARG(dif_pinmux_wakeup_cause_get(nullptr, &uint32_arg));
}
TEST_F(PinmuxTest, LockConfig) {
bool is_locked;
EXPECT_READ32(PINMUX_MIO_PERIPH_INSEL_REGWEN_0_REG_OFFSET, 1);
EXPECT_DIF_OK(dif_pinmux_is_locked(&dif_pinmux_, /*index=*/0,
kDifPinmuxLockTargetInsel, &is_locked));
EXPECT_FALSE(is_locked);
EXPECT_READ32(PINMUX_DIO_PAD_SLEEP_REGWEN_1_REG_OFFSET, 0);
EXPECT_DIF_OK(dif_pinmux_is_locked(&dif_pinmux_, /*index=*/1,
kDifPinmuxLockTargetDioSleep, &is_locked));
EXPECT_TRUE(is_locked);
EXPECT_WRITE32(PINMUX_MIO_PAD_SLEEP_REGWEN_2_REG_OFFSET, 0);
EXPECT_DIF_OK(
dif_pinmux_lock(&dif_pinmux_, /*index=*/2, kDifPinmuxLockTargetMioSleep));
}
TEST_F(PinmuxTest, InputSelection) {
EXPECT_READ32(PINMUX_MIO_PERIPH_INSEL_REGWEN_0_REG_OFFSET, 0);
EXPECT_EQ(dif_pinmux_input_select(&dif_pinmux_, /*peripheral_input=*/0,
/*insel=*/3),
kDifLocked);
EXPECT_READ32(PINMUX_MIO_PERIPH_INSEL_REGWEN_2_REG_OFFSET, 1);
EXPECT_WRITE32(PINMUX_MIO_PERIPH_INSEL_2_REG_OFFSET, 1);
EXPECT_DIF_OK(dif_pinmux_input_select(&dif_pinmux_, /*peripheral_input=*/2,
/*insel=*/1));
}
TEST_F(PinmuxTest, OutputSelection) {
EXPECT_READ32(PINMUX_MIO_OUTSEL_REGWEN_1_REG_OFFSET, 0);
EXPECT_EQ(dif_pinmux_output_select(&dif_pinmux_, /*mio_pad_output=*/1,
/*outsel=*/3),
kDifLocked);
EXPECT_READ32(PINMUX_MIO_OUTSEL_REGWEN_3_REG_OFFSET, 1);
EXPECT_WRITE32(PINMUX_MIO_OUTSEL_3_REG_OFFSET, 4);
EXPECT_DIF_OK(dif_pinmux_output_select(&dif_pinmux_, /*mio_pad_output=*/3,
/*outsel=*/4));
}
TEST_F(PinmuxTest, PadAttributes) {
dif_pinmux_pad_attr_t attrs = {
.slew_rate = 2,
.drive_strength = 5,
.flags = static_cast<dif_pinmux_pad_attr_flags_t>(
kDifPinmuxPadAttrInvertLevel | kDifPinmuxPadAttrPullResistorEnable |
kDifPinmuxPadAttrPullResistorUp),
};
dif_pinmux_pad_attr_t attrs_check;
EXPECT_READ32(PINMUX_MIO_PAD_ATTR_REGWEN_1_REG_OFFSET, 0);
EXPECT_EQ(dif_pinmux_pad_write_attrs(&dif_pinmux_, /*pad=*/1,
/*type=*/kDifPinmuxPadKindMio, attrs,
&attrs_check),
kDifLocked);
EXPECT_READ32(PINMUX_DIO_PAD_ATTR_REGWEN_2_REG_OFFSET, 0);
EXPECT_EQ(dif_pinmux_pad_write_attrs(&dif_pinmux_, /*pad=*/2,
/*type=*/kDifPinmuxPadKindDio, attrs,
&attrs_check),
kDifLocked);
EXPECT_READ32(PINMUX_MIO_PAD_ATTR_REGWEN_1_REG_OFFSET, 1);
EXPECT_WRITE32(PINMUX_MIO_PAD_ATTR_1_REG_OFFSET,
{
{PINMUX_MIO_PAD_ATTR_1_INVERT_1_BIT, 1},
{PINMUX_MIO_PAD_ATTR_1_PULL_EN_1_BIT, 1},
{PINMUX_MIO_PAD_ATTR_1_PULL_SELECT_1_BIT, 1},
{PINMUX_MIO_PAD_ATTR_1_SLEW_RATE_1_OFFSET, 2},
{PINMUX_MIO_PAD_ATTR_1_DRIVE_STRENGTH_1_OFFSET, 5},
});
EXPECT_READ32(PINMUX_MIO_PAD_ATTR_1_REG_OFFSET,
{
{PINMUX_MIO_PAD_ATTR_1_INVERT_1_BIT, 1},
{PINMUX_MIO_PAD_ATTR_1_PULL_EN_1_BIT, 1},
{PINMUX_MIO_PAD_ATTR_1_PULL_SELECT_1_BIT, 1},
{PINMUX_MIO_PAD_ATTR_1_SLEW_RATE_1_OFFSET, 2},
{PINMUX_MIO_PAD_ATTR_1_DRIVE_STRENGTH_1_OFFSET, 5},
});
EXPECT_DIF_OK(dif_pinmux_pad_write_attrs(&dif_pinmux_, /*pad=*/1,
/*type=*/kDifPinmuxPadKindMio, attrs,
&attrs_check));
EXPECT_EQ(attrs_check.slew_rate, attrs.slew_rate);
EXPECT_EQ(attrs_check.drive_strength, attrs.drive_strength);
EXPECT_EQ(attrs_check.flags, attrs.flags);
EXPECT_READ32(PINMUX_DIO_PAD_ATTR_REGWEN_3_REG_OFFSET, 1);
EXPECT_WRITE32(PINMUX_DIO_PAD_ATTR_3_REG_OFFSET,
{
{PINMUX_DIO_PAD_ATTR_3_INVERT_3_BIT, 1},
{PINMUX_DIO_PAD_ATTR_3_PULL_EN_3_BIT, 1},
{PINMUX_DIO_PAD_ATTR_3_PULL_SELECT_3_BIT, 1},
{PINMUX_DIO_PAD_ATTR_3_SLEW_RATE_3_OFFSET, 2},
{PINMUX_DIO_PAD_ATTR_3_DRIVE_STRENGTH_3_OFFSET, 5},
});
EXPECT_READ32(PINMUX_DIO_PAD_ATTR_3_REG_OFFSET,
{
{PINMUX_DIO_PAD_ATTR_3_INVERT_3_BIT, 0},
{PINMUX_DIO_PAD_ATTR_3_PULL_EN_3_BIT, 1},
{PINMUX_DIO_PAD_ATTR_3_PULL_SELECT_3_BIT, 1},
{PINMUX_DIO_PAD_ATTR_3_SLEW_RATE_3_OFFSET, 2},
{PINMUX_DIO_PAD_ATTR_3_DRIVE_STRENGTH_3_OFFSET, 5},
});
EXPECT_EQ(dif_pinmux_pad_write_attrs(&dif_pinmux_, /*pad=*/3,
/*type=*/kDifPinmuxPadKindDio, attrs,
&attrs_check),
kDifError);
EXPECT_EQ(attrs_check.slew_rate, attrs.slew_rate);
EXPECT_EQ(attrs_check.drive_strength, attrs.drive_strength);
EXPECT_EQ(attrs_check.flags, kDifPinmuxPadAttrPullResistorEnable |
kDifPinmuxPadAttrPullResistorUp);
EXPECT_READ32(PINMUX_MIO_PAD_ATTR_1_REG_OFFSET,
{
{PINMUX_MIO_PAD_ATTR_1_KEEPER_EN_1_BIT, 1},
{PINMUX_MIO_PAD_ATTR_1_OD_EN_1_BIT, 1},
{PINMUX_MIO_PAD_ATTR_1_SLEW_RATE_1_OFFSET, 1},
{PINMUX_MIO_PAD_ATTR_1_DRIVE_STRENGTH_1_OFFSET, 3},
});
EXPECT_DIF_OK(dif_pinmux_pad_get_attrs(
&dif_pinmux_, /*pad=*/1, /*type=*/kDifPinmuxPadKindMio, &attrs_check));
EXPECT_EQ(attrs_check.slew_rate, 1);
EXPECT_EQ(attrs_check.drive_strength, 3);
EXPECT_EQ(attrs_check.flags,
kDifPinmuxPadAttrKeeper | kDifPinmuxPadAttrOpenDrain);
}
TEST_F(PinmuxTest, SleepModeConfig) {
EXPECT_READ32(PINMUX_MIO_PAD_SLEEP_REGWEN_0_REG_OFFSET, 0);
EXPECT_EQ(
dif_pinmux_pad_sleep_enable(&dif_pinmux_, /*pad=*/0, kDifPinmuxPadKindMio,
kDifPinmuxSleepModeHighZ),
kDifLocked);
EXPECT_READ32(PINMUX_DIO_PAD_SLEEP_REGWEN_1_REG_OFFSET, 0);
EXPECT_EQ(dif_pinmux_pad_sleep_disable(&dif_pinmux_, /*pad=*/1,
kDifPinmuxPadKindDio),
kDifLocked);
EXPECT_READ32(PINMUX_MIO_PAD_SLEEP_REGWEN_1_REG_OFFSET, 1);
EXPECT_WRITE32(PINMUX_MIO_PAD_SLEEP_MODE_1_REG_OFFSET,
kDifPinmuxSleepModeHighZ);
EXPECT_WRITE32(PINMUX_MIO_PAD_SLEEP_EN_1_REG_OFFSET,
{{PINMUX_MIO_PAD_SLEEP_EN_1_EN_1_BIT, 1}});
EXPECT_DIF_OK(dif_pinmux_pad_sleep_enable(
&dif_pinmux_, /*pad=*/1, kDifPinmuxPadKindMio, kDifPinmuxSleepModeHighZ));
EXPECT_READ32(PINMUX_DIO_PAD_SLEEP_REGWEN_2_REG_OFFSET, 1);
EXPECT_WRITE32(PINMUX_DIO_PAD_SLEEP_EN_2_REG_OFFSET,
{{PINMUX_DIO_PAD_SLEEP_EN_2_EN_2_BIT, 0}});
EXPECT_DIF_OK(dif_pinmux_pad_sleep_disable(&dif_pinmux_, /*pad=*/2,
kDifPinmuxPadKindDio));
}
TEST_F(PinmuxTest, SleepStatus) {
bool in_sleep_mode;
EXPECT_READ32(PINMUX_MIO_PAD_SLEEP_STATUS_0_REG_OFFSET, 0xfffffff7u);
EXPECT_DIF_OK(dif_pinmux_pad_sleep_get_state(
&dif_pinmux_, /*pad=*/3, kDifPinmuxPadKindMio, &in_sleep_mode));
EXPECT_FALSE(in_sleep_mode);
EXPECT_READ32(PINMUX_DIO_PAD_SLEEP_STATUS_REG_OFFSET, 0x00000004u);
EXPECT_DIF_OK(dif_pinmux_pad_sleep_get_state(
&dif_pinmux_, /*pad=*/2, kDifPinmuxPadKindDio, &in_sleep_mode));
EXPECT_TRUE(in_sleep_mode);
EXPECT_READ32(PINMUX_MIO_PAD_SLEEP_STATUS_0_REG_OFFSET, 0xffff7777u);
EXPECT_WRITE32(PINMUX_MIO_PAD_SLEEP_STATUS_0_REG_OFFSET, 0xffff7757u);
EXPECT_DIF_OK(dif_pinmux_pad_sleep_clear_state(&dif_pinmux_, /*pad=*/5,
kDifPinmuxPadKindMio));
}
TEST_F(PinmuxTest, WakeupConfig) {
dif_pinmux_wakeup_config_t config = {
.signal_filter = kDifToggleDisabled,
.pad_type = kDifPinmuxPadKindMio,
.pad_select = 4,
.mode = kDifPinmuxWakeupModeTimedHigh,
.counter_threshold = 23,
};
EXPECT_READ32(PINMUX_WKUP_DETECTOR_REGWEN_1_REG_OFFSET, 0);
EXPECT_EQ(dif_pinmux_wakeup_detector_disable(&dif_pinmux_, /*detector=*/1),
kDifLocked);
EXPECT_READ32(PINMUX_WKUP_DETECTOR_REGWEN_0_REG_OFFSET, 0);
EXPECT_EQ(
dif_pinmux_wakeup_detector_enable(&dif_pinmux_, /*detector=*/0, config),
kDifLocked);
EXPECT_READ32(PINMUX_WKUP_DETECTOR_REGWEN_2_REG_OFFSET, 1);
EXPECT_WRITE32(PINMUX_WKUP_DETECTOR_EN_2_REG_OFFSET, 0);
EXPECT_DIF_OK(
dif_pinmux_wakeup_detector_disable(&dif_pinmux_, /*detector=*/2));
EXPECT_READ32(PINMUX_WKUP_DETECTOR_REGWEN_3_REG_OFFSET, 1);
EXPECT_WRITE32(PINMUX_WKUP_DETECTOR_EN_3_REG_OFFSET, 0);
EXPECT_WRITE32(PINMUX_WKUP_DETECTOR_3_REG_OFFSET,
{
{PINMUX_WKUP_DETECTOR_3_MODE_3_OFFSET,
PINMUX_WKUP_DETECTOR_0_MODE_0_VALUE_TIMEDHIGH},
{PINMUX_WKUP_DETECTOR_3_FILTER_3_BIT, 0},
{PINMUX_WKUP_DETECTOR_3_MIODIO_3_BIT, 0},
});
EXPECT_WRITE32(PINMUX_WKUP_DETECTOR_CNT_TH_3_REG_OFFSET, 23);
EXPECT_WRITE32(PINMUX_WKUP_DETECTOR_PADSEL_3_REG_OFFSET, 4);
EXPECT_WRITE32(PINMUX_WKUP_DETECTOR_EN_3_REG_OFFSET, 1);
EXPECT_DIF_OK(
dif_pinmux_wakeup_detector_enable(&dif_pinmux_, /*detector=*/3, config));
config.signal_filter = kDifToggleEnabled;
config.pad_select = 3;
config.pad_type = kDifPinmuxPadKindDio;
config.mode = kDifPinmuxWakeupModeAnyEdge;
EXPECT_READ32(PINMUX_WKUP_DETECTOR_REGWEN_3_REG_OFFSET, 1);
EXPECT_WRITE32(PINMUX_WKUP_DETECTOR_EN_3_REG_OFFSET, 0);
EXPECT_WRITE32(PINMUX_WKUP_DETECTOR_3_REG_OFFSET,
{
{PINMUX_WKUP_DETECTOR_3_MODE_3_OFFSET,
PINMUX_WKUP_DETECTOR_0_MODE_0_VALUE_EDGE},
{PINMUX_WKUP_DETECTOR_3_FILTER_3_BIT, 1},
{PINMUX_WKUP_DETECTOR_3_MIODIO_3_BIT, 1},
});
EXPECT_WRITE32(PINMUX_WKUP_DETECTOR_PADSEL_3_REG_OFFSET, 3);
EXPECT_WRITE32(PINMUX_WKUP_DETECTOR_EN_3_REG_OFFSET, 1);
EXPECT_DIF_OK(
dif_pinmux_wakeup_detector_enable(&dif_pinmux_, /*detector=*/3, config));
}
TEST_F(PinmuxTest, WakeupCause) {
uint32_t detector_map;
EXPECT_READ32(PINMUX_WKUP_CAUSE_REG_OFFSET, 0x4);
EXPECT_DIF_OK(dif_pinmux_wakeup_cause_get(&dif_pinmux_, &detector_map));
EXPECT_EQ(detector_map, 4);
EXPECT_WRITE32(PINMUX_WKUP_CAUSE_REG_OFFSET, 0x0);
EXPECT_DIF_OK(dif_pinmux_wakeup_cause_clear(&dif_pinmux_));
}
} // namespace
} // namespace dif_pinmux_unittest