/*
 * Copyright (c) 2022 Linaro Limited
 *
 * SPDX-License-Identifier: Apache-2.0
 */

#include <ztest.h>
#include <soc.h>
#include <zephyr/drivers/clock_control.h>
#include <zephyr/drivers/clock_control/stm32_clock_control.h>
#include <zephyr/logging/log.h>
LOG_MODULE_REGISTER(test);

#define DT_NO_CLOCK 0xFFFFU

/* Not device related, but keep it to ensure core clock config is correct */
static void test_sysclk_freq(void)
{
	uint32_t soc_sys_clk_freq;

	soc_sys_clk_freq = HAL_RCC_GetSysClockFreq();

	zassert_equal(CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC, soc_sys_clk_freq,
			"Expected sysclockfreq: %d. Actual sysclockfreq: %d",
			CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC, soc_sys_clk_freq);
}

#if DT_NODE_HAS_STATUS(DT_NODELABEL(i2c1), okay)

#if DT_HAS_COMPAT_STATUS_OKAY(st_stm32_i2c_v1)
#define DT_DRV_COMPAT st_stm32_i2c_v1
#elif DT_HAS_COMPAT_STATUS_OKAY(st_stm32_i2c_v2)
#define DT_DRV_COMPAT st_stm32_i2c_v2
#endif

#if STM32_DT_INST_DEV_OPT_CLOCK_SUPPORT
#define STM32_I2C_OPT_CLOCK_SUPPORT 1
#else
#define STM32_I2C_OPT_CLOCK_SUPPORT 0
#endif

static void test_i2c_clk_config(void)
{
	static const struct stm32_pclken pclken[] = STM32_DT_CLOCKS(DT_NODELABEL(i2c1));

	uint32_t dev_dt_clk_freq, dev_actual_clk_freq;
	uint32_t dev_actual_clk_src;
	int r;

	/* Test clock_on(gating clock) */
	r = clock_control_on(DEVICE_DT_GET(STM32_CLOCK_CONTROL_NODE),
				(clock_control_subsys_t) &pclken[0]);
	zassert_true((r == 0), "Could not enable I2C gating clock");

	zassert_true(__HAL_RCC_I2C1_IS_CLK_ENABLED(), "I2C1 gating clock should be on");
	TC_PRINT("I2C1 gating clock on\n");

	if (IS_ENABLED(STM32_I2C_OPT_CLOCK_SUPPORT) && DT_NUM_CLOCKS(DT_NODELABEL(i2c1)) > 1) {
		/* Test clock_on(ker_clk) */
		r = clock_control_configure(DEVICE_DT_GET(STM32_CLOCK_CONTROL_NODE),
					    (clock_control_subsys_t) &pclken[1],
					    NULL);
		zassert_true((r == 0), "Could not enable I2C soure clock");
		TC_PRINT("I2C1 source clock configured\n");

		/* Test clock source */
		dev_actual_clk_src = __HAL_RCC_GET_I2C1_SOURCE();

		if (pclken[1].bus == STM32_SRC_HSI) {
			zassert_equal(dev_actual_clk_src, RCC_I2C1CLKSOURCE_HSI,
					"Expected I2C src: HSI (0x%lx). Actual I2C src: 0x%x",
					RCC_I2C1CLKSOURCE_HSI, dev_actual_clk_src);
		} else if (pclken[1].bus == STM32_SRC_SYSCLK) {
			zassert_equal(dev_actual_clk_src, RCC_I2C1CLKSOURCE_SYSCLK,
					"Expected I2C src: SYSCLK (0x%lx). Actual I2C src: 0x%x",
					RCC_I2C1CLKSOURCE_SYSCLK, dev_actual_clk_src);
		} else {
			zassert_true(0, "Unexpected src clk (%d)", dev_actual_clk_src);
		}

		/* Test get_rate(srce clk) */
		r = clock_control_get_rate(DEVICE_DT_GET(STM32_CLOCK_CONTROL_NODE),
					(clock_control_subsys_t) &pclken[1],
					&dev_dt_clk_freq);
		zassert_true((r == 0), "Could not get I2C clk srce freq");

		dev_actual_clk_freq = HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_I2C1);
		zassert_equal(dev_dt_clk_freq, dev_actual_clk_freq,
				"Expected freq: %d Hz. Actual clk: %d Hz",
				dev_dt_clk_freq, dev_actual_clk_freq);

		TC_PRINT("I2C1 clock source rate: %d Hz\n", dev_dt_clk_freq);
	} else {
		zassert_true((DT_NUM_CLOCKS(DT_NODELABEL(i2c1)) == 1), "test config issue");
		/* No alt clock available, get rate from gating clock */

		/* Test get_rate */
		r = clock_control_get_rate(DEVICE_DT_GET(STM32_CLOCK_CONTROL_NODE),
					(clock_control_subsys_t) &pclken[0],
					&dev_dt_clk_freq);
		zassert_true((r == 0), "Could not get I2C clk freq");

		dev_actual_clk_freq = HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_I2C1);
		zassert_equal(dev_dt_clk_freq, dev_actual_clk_freq,
				"Expected freq: %d Hz. Actual freq: %d Hz",
				dev_dt_clk_freq, dev_actual_clk_freq);

		TC_PRINT("I2C1 clock source rate: %d Hz\n", dev_dt_clk_freq);
	}

	/* Test clock_off(gating clk) */
	r = clock_control_off(DEVICE_DT_GET(STM32_CLOCK_CONTROL_NODE),
				(clock_control_subsys_t) &pclken[0]);
	zassert_true((r == 0), "Could not disable I2C gating clk");

	zassert_true(!__HAL_RCC_I2C1_IS_CLK_ENABLED(), "I2C1 gating clk should be off");
	TC_PRINT("I2C1 gating clk off\n");

	/* Test clock_off(srce) */
	/* Not supported today */
}
#else
static void test_i2c_clk_config(void) {}
#endif

#if DT_NODE_HAS_STATUS(DT_NODELABEL(lptim1), okay)

#undef DT_DRV_COMPAT
#define DT_DRV_COMPAT st_stm32_lptim

#if STM32_DT_INST_DEV_OPT_CLOCK_SUPPORT
#define STM32_LPTIM_OPT_CLOCK_SUPPORT 1
#else
#define STM32_LPTIM_OPT_CLOCK_SUPPORT 0
#endif

static void test_lptim_clk_config(void)
{
	static const struct stm32_pclken pclken[] = STM32_DT_CLOCKS(DT_NODELABEL(lptim1));

	uint32_t dev_dt_clk_freq, dev_actual_clk_freq;
	uint32_t dev_actual_clk_src;
	int r;

	/* Test clock_on(gating clock) */
	r = clock_control_on(DEVICE_DT_GET(STM32_CLOCK_CONTROL_NODE),
				(clock_control_subsys_t) &pclken[0]);
	zassert_true((r == 0), "Could not enable LPTIM gating clock");

	zassert_true(__HAL_RCC_LPTIM1_IS_CLK_ENABLED(), "LPTIM1 gating clock should be on");
	TC_PRINT("LPTIM1 gating clock on\n");

	if (IS_ENABLED(STM32_LPTIM_OPT_CLOCK_SUPPORT) && DT_NUM_CLOCKS(DT_NODELABEL(lptim1)) > 1) {
		/* Test clock_on(ker_clk) */
		r = clock_control_configure(DEVICE_DT_GET(STM32_CLOCK_CONTROL_NODE),
					    (clock_control_subsys_t) &pclken[1],
					    NULL);
		zassert_true((r == 0), "Could not enable LPTIM1 soure clock");
		TC_PRINT("LPTIM1 source clock configured\n");

		/* Test clock source */
		dev_actual_clk_src = __HAL_RCC_GET_LPTIM1_SOURCE();

		if (pclken[1].bus == STM32_SRC_LSE) {
			zassert_equal(dev_actual_clk_src, RCC_LPTIM1CLKSOURCE_LSE,
					"Expected LPTIM1 src: LSE (0x%lx). Actual LPTIM1 src: 0x%x",
					RCC_LPTIM1CLKSOURCE_LSE, dev_actual_clk_src);
		} else if (pclken[1].bus == STM32_SRC_LSI) {
			zassert_equal(dev_actual_clk_src, RCC_LPTIM1CLKSOURCE_LSI,
					"Expected LPTIM1 src: LSI (0x%lx). Actual LPTIM1 src: 0x%x",
					RCC_LPTIM1CLKSOURCE_LSI, dev_actual_clk_src);
		} else {
			zassert_true(0, "Unexpected src clk (%d)", dev_actual_clk_src);
		}

		/* Test get_rate(srce clk) */
		r = clock_control_get_rate(DEVICE_DT_GET(STM32_CLOCK_CONTROL_NODE),
					(clock_control_subsys_t) &pclken[1],
					&dev_dt_clk_freq);
		zassert_true((r == 0), "Could not get LPTIM1 clk srce freq");

		dev_actual_clk_freq = HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_LPTIM1);
		zassert_equal(dev_dt_clk_freq, dev_actual_clk_freq,
				"Expected DT freq: %d Hz. Actual freq: %d Hz",
				dev_dt_clk_freq, dev_actual_clk_freq);

		TC_PRINT("LPTIM1 clock source rate: %d Hz\n", dev_dt_clk_freq);
	} else {
		zassert_true((DT_NUM_CLOCKS(DT_NODELABEL(lptim1)) == 1), "test config issue");
		/* No alt clock available, get rate from gating clock */

		/* Test get_rate */
		r = clock_control_get_rate(DEVICE_DT_GET(STM32_CLOCK_CONTROL_NODE),
					(clock_control_subsys_t) &pclken[0],
					&dev_dt_clk_freq);
		zassert_true((r == 0), "Could not get LPTIM1 clk freq");

		dev_actual_clk_freq = HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_LPTIM1);
		zassert_equal(dev_dt_clk_freq, dev_actual_clk_freq,
				"Expected DT freq: %d Hz. Actual freq: %d Hz",
				dev_dt_clk_freq, dev_actual_clk_freq);

		TC_PRINT("LPTIM1 clock source rate: %d Hz\n", dev_dt_clk_freq);
	}

	/* Test clock_off(reg_clk) */
	r = clock_control_off(DEVICE_DT_GET(STM32_CLOCK_CONTROL_NODE),
				(clock_control_subsys_t) &pclken[0]);
	zassert_true((r == 0), "Could not disable LPTIM1 gating clk");

	zassert_true(!__HAL_RCC_I2C1_IS_CLK_ENABLED(), "LPTIM1 gating clk should be off");
	TC_PRINT("LPTIM1 gating clk off\n");

	/* Test clock_off(srce) */
	/* Not supported today */
}
#else
static void test_lptim_clk_config(void) {}
#endif

void test_main(void)
{
	ztest_test_suite(test_stm32_common_devices_clocks,
		ztest_unit_test(test_sysclk_freq),
		ztest_unit_test(test_i2c_clk_config),
		ztest_unit_test(test_lptim_clk_config)
			 );
	ztest_run_test_suite(test_stm32_common_devices_clocks);
}
