/*
 * Copyright (c) 2023 Renesas Electronics Corporation
 *
 * SPDX-License-Identifier: Apache-2.0
 */

#include <zephyr/device.h>
#include <zephyr/drivers/clock_control.h>
#include <zephyr/drivers/clock_control/smartbond_clock_control.h>
#include <zephyr/drivers/timer/system_timer.h>
#include <zephyr/sys_clock.h>
#include <zephyr/spinlock.h>
#include <cmsis_core.h>
#include <zephyr/irq.h>
#include <da1469x_pdc.h>

#define COUNTER_SPAN BIT(24)
#define CYC_PER_TICK k_ticks_to_cyc_ceil32(1)
#define TICK_TO_CYC(tick) k_ticks_to_cyc_ceil32(tick)
#define CYC_TO_TICK(cyc) k_cyc_to_ticks_ceil32(cyc)
#define MAX_TICKS (((COUNTER_SPAN / 2) - CYC_PER_TICK) / (CYC_PER_TICK))
#define SMARTBOND_CLOCK_CONTROLLER DEVICE_DT_GET(DT_NODELABEL(osc))
/* Margin values are based on DA1469x characterization data */
#define RC32K_FREQ_POSITIVE_MARGIN_DUE_TO_VOLTAGE (675)
#define RC32K_FREQ_MARGIN_DUE_TO_TEMPERATURE (450)

static uint32_t last_timer_val_reg;
static uint32_t timer_val_31_24;

static uint32_t last_isr_val;
static uint32_t last_isr_val_rounded;
static uint32_t announced_ticks;

static uint32_t get_rc32k_max_frequency(void)
{
	/* According to DA1469x datasheet */
	uint32_t r32k_frequency = 37000;

	clock_control_get_rate(SMARTBOND_CLOCK_CONTROLLER,
				(clock_control_subsys_t)SMARTBOND_CLK_RC32K, &r32k_frequency);

	r32k_frequency += RC32K_FREQ_POSITIVE_MARGIN_DUE_TO_VOLTAGE +
			  RC32K_FREQ_MARGIN_DUE_TO_TEMPERATURE;
	return r32k_frequency;
}

static void set_reload(uint32_t val)
{
	TIMER2->TIMER2_RELOAD_REG = val & TIMER2_TIMER2_RELOAD_REG_TIM_RELOAD_Msk;
}

static uint32_t timer_val_32(void)
{
	uint32_t timer_val_reg;
	uint32_t val;

	timer_val_reg = TIMER2->TIMER2_TIMER_VAL_REG &
		TIMER2_TIMER2_TIMER_VAL_REG_TIM_TIMER_VALUE_Msk;
	if (timer_val_reg < last_timer_val_reg) {
		timer_val_31_24 += COUNTER_SPAN;
	}
	last_timer_val_reg = timer_val_reg;

	val = timer_val_31_24 + timer_val_reg;

	return val;
}

static uint32_t timer_val_32_noupdate(void)
{
	uint32_t timer_val_reg;
	uint32_t val;

	timer_val_reg = TIMER2->TIMER2_TIMER_VAL_REG &
		TIMER2_TIMER2_TIMER_VAL_REG_TIM_TIMER_VALUE_Msk;
	val = timer_val_31_24 + timer_val_reg;
	if (timer_val_reg < last_timer_val_reg) {
		val += COUNTER_SPAN;
	}

	return val;
}

void sys_clock_set_timeout(int32_t ticks, bool idle)
{
	uint32_t target_val;
	uint32_t timer_val;

	if (!IS_ENABLED(CONFIG_TICKLESS_KERNEL)) {
		return;
	}

	if (ticks == K_TICKS_FOREVER) {
		/* FIXME we could disable timer here */
	}

	/*
	 * When Watchdog is NOT enabled but power management is, system
	 * starts watchdog before PD_SYS is powered off.
	 * Watchdog default reload value is 0x1FFF (~82s for RC32K and 172s for RCX).
	 * After this time watchdog will reset system if not woken up before.
	 * When Watchdog is not configured power management freezes watchdog
	 * as soon as system is awaken. Following code makes sure that
	 * system never goes to sleep for longer time that watchdog reload value.
	 */
	if (!IS_ENABLED(CONFIG_WDT_SMARTBOND) && IS_ENABLED(CONFIG_PM)) {
		uint32_t watchdog_expire_ticks;

		if (CRG_TOP->CLK_RCX_REG & CRG_TOP_CLK_RCX_REG_RCX_ENABLE_Msk) {
			/*
			 * When LP clock is RCX, the watchdog is clocked by RCX clock
			 * divided by 320.
			 */
			watchdog_expire_ticks = SYS_WDOG->WATCHDOG_REG * 320;
		} else {
			/*
			 * When LP clock is not RCX, the watchdog is clocked by RC32K
			 * divided by 320. In this case watchdog value to LP clock
			 * ticks must be calculated according to XTAL32K frequency and
			 * RC32K maximum frequency.
			 */
			watchdog_expire_ticks = SYS_WDOG->WATCHDOG_REG *
				CONFIG_SYS_CLOCK_TICKS_PER_SEC / (get_rc32k_max_frequency() / 320);
		}
		if (watchdog_expire_ticks - 2 < ticks) {
			ticks = watchdog_expire_ticks - 2;
		}
	}
	ticks = (ticks == K_TICKS_FOREVER) ? MAX_TICKS : ticks;
	ticks = CLAMP(ticks - 1, 0, (int32_t)MAX_TICKS);

	timer_val = timer_val_32_noupdate();

	/* Calculate target timer value and align to full tick */
	target_val = timer_val + TICK_TO_CYC(ticks);
	target_val = ((target_val + CYC_PER_TICK - 1) / CYC_PER_TICK) * CYC_PER_TICK;

	set_reload(target_val);

	/*
	 * If time was so small that it already fired or should fire
	 * just now, mark interrupt as pending to avoid losing timer event.
	 * Condition is true when target_val (point in time that should be
	 * used for wakeup) is behind timer value or is equal to it.
	 * In that case we don't know if reload value was set in time or
	 * not but time expired anyway so make sure that interrupt is pending.
	 */
	if ((int32_t)(target_val - timer_val_32_noupdate() - 1) < 0) {
		NVIC_SetPendingIRQ(TIMER2_IRQn);
	}
}

uint32_t sys_clock_elapsed(void)
{
	if (!IS_ENABLED(CONFIG_TICKLESS_KERNEL)) {
		return 0;
	}

	return CYC_TO_TICK(timer_val_32_noupdate() - last_isr_val);
}

uint32_t sys_clock_cycle_get_32(void)
{
	return timer_val_32_noupdate();
}

void sys_clock_idle_exit(void)
{
	TIMER2->TIMER2_CTRL_REG |= TIMER2_TIMER2_CTRL_REG_TIM_EN_Msk;
}

void sys_clock_disable(void)
{
	TIMER2->TIMER2_CTRL_REG &= ~TIMER2_TIMER2_CTRL_REG_TIM_EN_Msk;
}

static void timer2_isr(const void *arg)
{
	uint32_t val;
	int32_t delta;
	int32_t dticks;

	ARG_UNUSED(arg);

	TIMER2->TIMER2_CLEAR_IRQ_REG = 1;

	val = timer_val_32();
	delta = (int32_t)(val - last_isr_val_rounded);
	last_isr_val = val;
	dticks = CYC_TO_TICK(delta);
	last_isr_val_rounded += TICK_TO_CYC(dticks);
	announced_ticks += dticks;
	sys_clock_announce(dticks);
}

static int sys_clock_driver_init(void)
{
#if CONFIG_PM
	uint8_t pdc_idx;
	uint8_t en_xtal;

	en_xtal = DT_NODE_HAS_STATUS(DT_NODELABEL(xtal32m), okay) ? MCU_PDC_EN_XTAL : 0;

	/* Enable wakeup by TIMER2 */
	pdc_idx = da1469x_pdc_add(MCU_PDC_TRIGGER_TIMER2, MCU_PDC_MASTER_M33, en_xtal);
	__ASSERT_NO_MSG(pdc_idx >= 0);
	da1469x_pdc_set(pdc_idx);
	da1469x_pdc_ack(pdc_idx);
#endif

	TIMER2->TIMER2_CTRL_REG = 0;
	TIMER2->TIMER2_PRESCALER_REG = 0;
	TIMER2->TIMER2_CTRL_REG |= TIMER2_TIMER2_CTRL_REG_TIM_CLK_EN_Msk;
	TIMER2->TIMER2_CTRL_REG |= TIMER2_TIMER2_CTRL_REG_TIM_FREE_RUN_MODE_EN_Msk |
				   TIMER2_TIMER2_CTRL_REG_TIM_IRQ_EN_Msk |
				   TIMER2_TIMER2_CTRL_REG_TIM_EN_Msk;

	IRQ_CONNECT(TIMER2_IRQn, _IRQ_PRIO_OFFSET, timer2_isr, 0, 0);
	irq_enable(TIMER2_IRQn);

	return 0;
}

SYS_INIT(sys_clock_driver_init, PRE_KERNEL_2, CONFIG_SYSTEM_CLOCK_INIT_PRIORITY);
