/*
 * Copyright (c) 2019-2020, Nordic Semiconductor ASA
 *
 * SPDX-License-Identifier: Apache-2.0
 */
#include <ztest.h>
#include <drivers/entropy.h>
#include <drivers/clock_control.h>
#include <drivers/clock_control/nrf_clock_control.h>
#include <hal/nrf_clock.h>

#include <logging/log.h>
LOG_MODULE_REGISTER(test);

#define TEST_TIME_MS 10000

#define HF_STARTUP_TIME_US 400

static bool test_end;

#include <hal/nrf_gpio.h>

static const struct device *entropy = DEVICE_DT_GET(DT_CHOSEN(zephyr_entropy));
static struct onoff_manager *hf_mgr;
static uint32_t iteration;

static void setup(void)
{
	zassert_true(device_is_ready(entropy), NULL);

	hf_mgr = z_nrf_clock_control_get_onoff(CLOCK_CONTROL_NRF_SUBSYS_HF);
	zassert_true(hf_mgr, NULL);

	iteration = 0;
}

static void teardown(void)
{
	/* empty */
}

static void bt_timeout_handler(struct k_timer *timer)
{
	static bool on;

	nrf_gpio_cfg_output(27);
	if (on) {
		on = false;
		nrf_gpio_pin_clear(27);
		z_nrf_clock_bt_ctlr_hf_release();
	} else {
		nrf_gpio_pin_set(27);
		on = true;
		z_nrf_clock_bt_ctlr_hf_request();
	}

	if (!(test_end && !on)) {
		k_timeout_t timeout;
		static bool long_timeout;

		if (!on) {
			timeout = Z_TIMEOUT_US(200);
		} else {
			timeout = Z_TIMEOUT_US(long_timeout ? 300 : 100);
			long_timeout = !long_timeout;
		}
		k_timer_start(timer, timeout, K_NO_WAIT);
	}
}

K_TIMER_DEFINE(timer1, bt_timeout_handler, NULL);

static void check_hf_status(const struct device *dev, bool exp_on,
			    bool sw_check)
{
	nrf_clock_hfclk_t type;

	nrf_clock_is_running(NRF_CLOCK, NRF_CLOCK_DOMAIN_HFCLK, &type);
	zassert_equal(type, exp_on ? NRF_CLOCK_HFCLK_HIGH_ACCURACY :
				NRF_CLOCK_HFCLK_LOW_ACCURACY,
			"%d: Clock expected to be %s",
			iteration, exp_on ? "on" : "off");

	if (sw_check) {
		enum clock_control_status status =
		     clock_control_get_status(dev, CLOCK_CONTROL_NRF_SUBSYS_HF);

		zassert_equal(status, exp_on ? CLOCK_CONTROL_STATUS_ON :
						CLOCK_CONTROL_STATUS_OFF,
				"%d: Unexpected status: %d", iteration, status);
	}

}

/* Test controls HF clock from two contexts: thread and timer interrupt.
 * In thread context clock is requested and released through standard onoff
 * API and in the timeout handler it is requested and released using API
 * dedicated to be used by Bluetooth Controller.
 *
 * Test runs in the loop to eventually lead to cases when clock controlling is
 * preempted by timeout handler. At certain points clock status is validated.
 */
static void test_onoff_interrupted(void)
{
	const struct device *clock_dev =
		device_get_binding(DT_LABEL(DT_INST(0, nordic_nrf_clock)));
	struct onoff_client cli;
	uint64_t start_time = k_uptime_get();
	uint64_t elapsed;
	uint64_t checkpoint = 1000;
	int err;
	uint8_t rand;
	int backoff;

	k_timer_start(&timer1, K_MSEC(1), K_NO_WAIT);

	while (1) {
		iteration++;

		err = entropy_get_entropy(entropy, &rand, 1);
		zassert_equal(err, 0, NULL);
		backoff = 3 * rand;

		sys_notify_init_spinwait(&cli.notify);
		err = onoff_request(hf_mgr, &cli);
		zassert_true(err >= 0, NULL);

		k_busy_wait(backoff);

		if (backoff > HF_STARTUP_TIME_US) {
			check_hf_status(clock_dev, true, true);
		}

		err = onoff_cancel_or_release(hf_mgr, &cli);
		zassert_true(err >= 0, NULL);

		elapsed = k_uptime_get() - start_time;
		if (elapsed > checkpoint) {
			printk("test continues\n");
			checkpoint += 1000;
		}

		if (elapsed > TEST_TIME_MS) {
			test_end = true;
			break;
		}
	}

	k_msleep(100);
	check_hf_status(clock_dev, false, true);
}

static void onoff_timeout_handler(struct k_timer *timer)
{
	static bool on;
	static struct onoff_client cli;
	static uint32_t cnt;
	int err;

	cnt++;
	if (on) {
		on = false;
		err = onoff_cancel_or_release(hf_mgr, &cli);
		zassert_true(err >= 0, NULL);
	} else {
		on = true;
		sys_notify_init_spinwait(&cli.notify);
		err = onoff_request(hf_mgr, &cli);
		zassert_true(err >= 0, "%d: Unexpected err: %d", cnt, err);
	}

	if (!(test_end && !on)) {
		k_timeout_t timeout;
		static bool long_timeout;

		if (!on) {
			timeout = Z_TIMEOUT_US(200);
		} else {
			timeout = Z_TIMEOUT_US(long_timeout ? 300 : 100);
			long_timeout = !long_timeout;
		}
		k_timer_start(timer, timeout, K_NO_WAIT);
	}
}

K_TIMER_DEFINE(timer2, onoff_timeout_handler, NULL);

/* Test controls HF clock from two contexts: thread and timer interrupt.
 * In thread context clock is requested and released through API
 * dedicated to be used by Bluetooth Controller and in the timeout handler it is
 * requested and released using standard onoffAPI .
 *
 * Test runs in the loop to eventually lead to cases when clock controlling is
 * preempted by timeout handler. At certain points clock status is validated.
 */
static void test_bt_interrupted(void)
{
	const struct device *clock_dev =
		device_get_binding(DT_LABEL(DT_INST(0, nordic_nrf_clock)));
	uint64_t start_time = k_uptime_get();
	uint64_t elapsed;
	uint64_t checkpoint = 1000;
	int err;
	uint8_t rand;
	int backoff;

	k_timer_start(&timer2, K_MSEC(1), K_NO_WAIT);

	while (1) {
		iteration++;

		err = entropy_get_entropy(entropy, &rand, 1);
		zassert_equal(err, 0, NULL);
		backoff = 3 * rand;

		z_nrf_clock_bt_ctlr_hf_request();

		k_busy_wait(backoff);

		if (backoff > HF_STARTUP_TIME_US) {
			check_hf_status(clock_dev, true, false);
		}

		z_nrf_clock_bt_ctlr_hf_release();

		elapsed = k_uptime_get() - start_time;
		if (elapsed > checkpoint) {
			printk("test continues\n");
			checkpoint += 1000;
		}

		if (elapsed > TEST_TIME_MS) {
			test_end = true;
			break;
		}
	}

	k_msleep(100);
	check_hf_status(clock_dev, false, true);
}

void test_main(void)
{
	ztest_test_suite(test_nrf_onoff_and_bt,
		ztest_unit_test_setup_teardown(test_onoff_interrupted,
					       setup, teardown),
		ztest_unit_test_setup_teardown(test_bt_interrupted,
					       setup, teardown)
			);
	ztest_run_test_suite(test_nrf_onoff_and_bt);
}
