blob: 0583382c2e0f36d9f21f56975085b74e9c3eca8c [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/base/mmio.h"
#include "sw/device/lib/dif/dif_aon_timer.h"
#include "sw/device/lib/dif/dif_pwrmgr.h"
#include "sw/device/lib/runtime/log.h"
#include "sw/device/lib/testing/check.h"
#include "sw/device/lib/testing/test_main.h"
#include "hw/top_earlgrey/sw/autogen/top_earlgrey.h" // Generated.
static dif_pwrmgr_t pwrmgr;
static dif_aon_timer_t aon_timer;
const test_config_t kTestConfig;
const dif_pwrmgr_wakeup_reason_t test_wakeup_reason = {
.types = kDifPwrmgrWakeupTypeRequest,
.request_sources = kDifPwrmgrWakeupRequestSourceFour,
};
const dif_pwrmgr_wakeup_reason_t por_wakeup_reason = {
.types = 0,
.request_sources = 0,
};
static bool compare_wakeup_reasons(const dif_pwrmgr_wakeup_reason_t *lhs,
const dif_pwrmgr_wakeup_reason_t *rhs) {
return lhs->types == rhs->types &&
lhs->request_sources == rhs->request_sources;
}
static void aon_timer_setup(dif_aon_timer_t *aon) {
// Make sure that wake-up timer is stopped.
CHECK(dif_aon_timer_wakeup_stop(aon) == kDifAonTimerOk);
// Make sure the wake-up IRQ is cleared to avoid false positive.
CHECK(dif_aon_timer_irq_acknowledge(aon, kDifAonTimerIrqWakeupThreshold) ==
kDifAonTimerOk);
bool is_pending;
CHECK(dif_aon_timer_irq_is_pending(aon, kDifAonTimerIrqWakeupThreshold,
&is_pending) == kDifAonTimerOk);
CHECK(!is_pending);
// Test the wake-up timer functionality by setting a small counter.
// Delay to compensate for AON Timer 200kHz clock (less should suffice, but
// to be on a cautious side - lets keep it at 100 for now).
CHECK(dif_aon_timer_wakeup_start(aon, 5, 0) == kDifAonTimerOk);
usleep(100);
}
bool test_main(void) {
bool test_passed = false;
// Initialize pwrmgr
CHECK(dif_pwrmgr_init(
(dif_pwrmgr_params_t){
.base_addr =
mmio_region_from_addr(TOP_EARLGREY_PWRMGR_AON_BASE_ADDR),
},
&pwrmgr) == kDifPwrmgrOk);
// Initialize aon_timer
dif_aon_timer_params_t params = {
.base_addr = mmio_region_from_addr(TOP_EARLGREY_AON_TIMER_AON_BASE_ADDR),
};
CHECK(dif_aon_timer_init(params, &aon_timer) == kDifAonTimerOk);
// Assuming the chip hasn't slept yet, wakeup reason should be empty.
dif_pwrmgr_wakeup_reason_t wakeup_reason;
CHECK(dif_pwrmgr_wakeup_reason_get(&pwrmgr, &wakeup_reason) == kDifPwrmgrOk);
if (compare_wakeup_reasons(&wakeup_reason, &por_wakeup_reason)) {
LOG_INFO("Powered up for the first time, begin test");
} else if (compare_wakeup_reasons(&wakeup_reason, &test_wakeup_reason)) {
test_passed = true;
LOG_INFO("Aon timer wakeup detected");
} else {
CHECK(false);
}
if (!test_passed) {
// setup aon timer wakeup
aon_timer_setup(&aon_timer);
// Enable low power on the next WFI with default settings.
// All clocks and power domains are turned off during low power.
dif_pwrmgr_domain_config_t config;
config = 0;
CHECK(dif_pwrmgr_set_request_sources(&pwrmgr, kDifPwrmgrReqTypeWakeup,
kDifPwrmgrWakeupRequestSourceFour) ==
kDifPwrmgrConfigOk);
CHECK(dif_pwrmgr_set_domain_config(&pwrmgr, config) == kDifPwrmgrConfigOk);
CHECK(dif_pwrmgr_low_power_set_enabled(&pwrmgr, kDifPwrmgrToggleEnabled) ==
kDifPwrmgrConfigOk);
// Enter low power mode.
wait_for_interrupt();
}
return test_passed;
}