/*
 * Copyright (c) 2019-2020, Nordic Semiconductor ASA
 *
 * SPDX-License-Identifier: Apache-2.0
 */
#include <zephyr/ztest.h>
#include <zephyr/drivers/clock_control.h>
#include <zephyr/drivers/clock_control/nrf_clock_control.h>
#include <hal/nrf_clock.h>
#include <zephyr/drivers/sensor.h>
#include <zephyr/logging/log.h>
LOG_MODULE_REGISTER(test);

#ifndef CONFIG_CLOCK_CONTROL_NRF_K32SRC_RC
#error "LFCLK must use RC source"
#endif

#define CALIBRATION_PROCESS_TIME_MS 35

extern void mock_temp_nrf5_value_set(struct sensor_value *val);

static void turn_on_clock(const struct device *dev,
			  clock_control_subsys_t subsys)
{
	int err;
	int res;
	struct onoff_client cli;
	struct onoff_manager *mgr = z_nrf_clock_control_get_onoff(subsys);

	sys_notify_init_spinwait(&cli.notify);
	err = onoff_request(mgr, &cli);
	if (err < 0) {
		zassert_false(true, "Failed to start clock");
	}
	while (sys_notify_fetch_result(&cli.notify, &res) != 0) {
	}
}

static void turn_off_clock(const struct device *dev,
			   clock_control_subsys_t subsys)
{
	int err;
	struct onoff_manager *mgr = z_nrf_clock_control_get_onoff(subsys);

	do {
		err = onoff_release(mgr);
	} while (err >= 0);

	while (clock_control_get_status(dev, subsys) !=
		CLOCK_CONTROL_STATUS_OFF) {
	}
}

#define TEST_CALIBRATION(exp_cal, exp_skip, sleep_ms) \
	test_calibration(exp_cal, exp_skip, sleep_ms, __LINE__)

/* Function tests if during given time expected number of calibrations and
 * skips occurs.
 */
static void test_calibration(uint32_t exp_cal, uint32_t exp_skip,
				uint32_t sleep_ms, uint32_t line)
{
	int cal_cnt;
	int skip_cnt;

	cal_cnt = z_nrf_clock_calibration_count();
	skip_cnt = z_nrf_clock_calibration_skips_count();

	k_sleep(K_MSEC(sleep_ms));

	cal_cnt = z_nrf_clock_calibration_count() - cal_cnt;
	skip_cnt = z_nrf_clock_calibration_skips_count() - skip_cnt;

	zassert_equal(cal_cnt, exp_cal,
			"%d: Unexpected number of calibrations (%d, exp:%d)",
			line, cal_cnt, exp_cal);
	zassert_equal(skip_cnt, exp_skip,
			"%d: Unexpected number of skips (%d, exp:%d)",
			line, skip_cnt, exp_skip);
}

/* Function pends until calibration counter is performed. When function leaves,
 * it is just after calibration.
 */
static void sync_just_after_calibration(void)
{
	uint32_t cal_cnt = z_nrf_clock_calibration_count();

	/* wait until calibration is performed. */
	while (z_nrf_clock_calibration_count() == cal_cnt) {
		k_sleep(K_MSEC(1));
	}
}

/* Test checks if calibration and calibration skips are performed according
 * to timing configuration.
 */
ZTEST(nrf_clock_calibration, test_basic_clock_calibration)
{
	int wait_ms = CONFIG_CLOCK_CONTROL_NRF_CALIBRATION_PERIOD *
		(CONFIG_CLOCK_CONTROL_NRF_CALIBRATION_MAX_SKIP + 1) +
		CALIBRATION_PROCESS_TIME_MS;
	struct sensor_value value = { .val1 = 0, .val2 = 0 };

	mock_temp_nrf5_value_set(&value);
	sync_just_after_calibration();

	TEST_CALIBRATION(1, CONFIG_CLOCK_CONTROL_NRF_CALIBRATION_MAX_SKIP,
			 wait_ms);
}

/* Test checks if calibration happens just after clock is enabled. */
ZTEST(nrf_clock_calibration, test_calibration_after_enabling_lfclk)
{
	if (IS_ENABLED(CONFIG_SOC_NRF52832)) {
		/* On nrf52832 LF clock cannot be stopped because it leads
		 * to RTC COUNTER register reset and that is unexpected by
		 * system clock which is disrupted and may hang in the test.
		 */
		ztest_test_skip();
	}

	const struct device *const clk_dev = DEVICE_DT_GET_ONE(nordic_nrf_clock);
	struct sensor_value value = { .val1 = 0, .val2 = 0 };

	zassert_true(device_is_ready(clk_dev), "Device is not ready");

	mock_temp_nrf5_value_set(&value);

	turn_off_clock(clk_dev, CLOCK_CONTROL_NRF_SUBSYS_LF);

	k_busy_wait(10000);

	turn_on_clock(clk_dev, CLOCK_CONTROL_NRF_SUBSYS_LF);

	TEST_CALIBRATION(1, 0,
			 CONFIG_CLOCK_CONTROL_NRF_CALIBRATION_PERIOD);
}

/* Test checks if temperature change triggers calibration. */
ZTEST(nrf_clock_calibration, test_temp_change_triggers_calibration)
{
	struct sensor_value value = { .val1 = 0, .val2 = 0 };

	mock_temp_nrf5_value_set(&value);
	sync_just_after_calibration();

	/* change temperature by 0.25'C which should not trigger calibration */
	value.val2 += ((CONFIG_CLOCK_CONTROL_NRF_CALIBRATION_TEMP_DIFF - 1) *
			250000);
	mock_temp_nrf5_value_set(&value);

	/* expected one skip */
	TEST_CALIBRATION(0, CONFIG_CLOCK_CONTROL_NRF_CALIBRATION_MAX_SKIP,
				CONFIG_CLOCK_CONTROL_NRF_CALIBRATION_MAX_SKIP *
				CONFIG_CLOCK_CONTROL_NRF_CALIBRATION_PERIOD +
				CALIBRATION_PROCESS_TIME_MS);

	TEST_CALIBRATION(1, 0,
			 CONFIG_CLOCK_CONTROL_NRF_CALIBRATION_PERIOD + 40);

	value.val2 += (CONFIG_CLOCK_CONTROL_NRF_CALIBRATION_TEMP_DIFF * 250000);
	mock_temp_nrf5_value_set(&value);

	/* expect calibration due to temp change. */
	TEST_CALIBRATION(1, 0,
			 CONFIG_CLOCK_CONTROL_NRF_CALIBRATION_PERIOD + 40);
}

/* Test checks if z_nrf_clock_calibration_force_start() results in immediate
 * calibration.
 */
ZTEST(nrf_clock_calibration, test_force_calibration)
{
	sync_just_after_calibration();

	z_nrf_clock_calibration_force_start();

	/*expect immediate calibration */
	TEST_CALIBRATION(1, 0,
		CALIBRATION_PROCESS_TIME_MS + 5);

	/* and back to scheduled operation. */
	TEST_CALIBRATION(1, CONFIG_CLOCK_CONTROL_NRF_CALIBRATION_MAX_SKIP,
		CONFIG_CLOCK_CONTROL_NRF_CALIBRATION_PERIOD *
		(CONFIG_CLOCK_CONTROL_NRF_CALIBRATION_MAX_SKIP + 1) +
		CALIBRATION_PROCESS_TIME_MS);

}
ZTEST_SUITE(nrf_clock_calibration, NULL, NULL, NULL, NULL, NULL);
