/*
 * Copyright (c) 2019 Centaur Analytics, Inc
 *
 * SPDX-License-Identifier: Apache-2.0
 */

#define DT_DRV_COMPAT st_stm32_window_watchdog

#include <drivers/watchdog.h>
#include <soc.h>
#include <errno.h>
#include <assert.h>
#include <drivers/clock_control/stm32_clock_control.h>
#include <drivers/clock_control.h>

#include "wdt_wwdg_stm32.h"

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

#define WWDG_INTERNAL_DIVIDER   4096U
#define WWDG_RESET_LIMIT    WWDG_COUNTER_MIN
#define WWDG_COUNTER_MIN    0x40
#define WWDG_COUNTER_MAX    0x7f

/* The timeout of the WWDG in milliseconds is calculated by the below formula:
 *
 * t_WWDG = 1000 * ((counter & 0x3F) + 1) / f_WWDG (ms)
 *
 * where:
 *  - t_WWDG: WWDG timeout
 *  - counter: a value in [0x40, 0x7F] representing the cycles before timeout.
 *             Giving the counter a value below 0x40, will result in an
 *             immediate system reset. A reset is produced when the counter
 *             rolls over from 0x40 to 0x3F.
 *  - f_WWDG: the frequency of the WWDG clock. This can be calculated by the
 *            below formula:
 *    f_WWDG = f_PCLK / (4096 * prescaler) (Hz)
 *    where:
 *     - f_PCLK: the clock frequency of the system
 *     - 4096: the constant internal divider
 *     - prescaler: the programmable divider with valid values of 1, 2, 4 or 8
 *
 * The minimum timeout is calculated with:
 *  - counter = 0x40
 *  - prescaler = 1
 * The maximim timeout is calculated with:
 *  - counter = 0x7F
 *  - prescaler = 8
 *
 * E.g. for f_PCLK = 2MHz
 *  t_WWDG_min = 1000 * ((0x40 & 0x3F) + 1) / (2000000 / (4096 * 1))
 *             = 2.048 ms
 *  t_WWDG_max = 1000 * ((0x7F & 0x3F) + 1) / (2000000 / (4096 * 8))
 *             = 1048.576 ms
 */

#define ABS_DIFF_UINT(a, b)  ((a) > (b) ? (a) - (b) : (b) - (a))
#define WWDG_TIMEOUT_ERROR_MARGIN   (100 * USEC_PER_MSEC)
#define IS_WWDG_TIMEOUT(__TIMEOUT_GOLDEN__, __TIMEOUT__)  \
	(ABS_DIFF_UINT(__TIMEOUT_GOLDEN__, __TIMEOUT__) < \
	 WWDG_TIMEOUT_ERROR_MARGIN)

static void wwdg_stm32_irq_config(struct device *dev);

static u32_t wwdg_stm32_get_pclk(struct device *dev)
{
	struct device *clk = device_get_binding(STM32_CLOCK_CONTROL_NAME);
	const struct wwdg_stm32_config *cfg = WWDG_STM32_CFG(dev);
	u32_t pclk_rate;

	__ASSERT_NO_MSG(clk);

	if (clock_control_get_rate(clk, (clock_control_subsys_t *) &cfg->pclken,
			       &pclk_rate) < 0) {
		LOG_ERR("Failed call clock_control_get_rate");
		return -EIO;
	}

	return pclk_rate;
}

/**
 * @brief Calculates the timeout in microseconds.
 *
 * @param dev Pointer to device structure.
 * @param prescaler The prescaler value.
 * @param counter The counter value.
 * @return The timeout calculated in microseconds.
 */
static u32_t wwdg_stm32_get_timeout(struct device *dev, u32_t prescaler,
				    u32_t counter)
{
	u32_t divider = WWDG_INTERNAL_DIVIDER * (1 << (prescaler >> 7));
	float f_wwdg = (float)wwdg_stm32_get_pclk(dev) / divider;

	return USEC_PER_SEC * (((counter & 0x3F) + 1) / f_wwdg);
}

/**
 * @brief Calculates prescaler & counter values.
 *
 * @param dev Pointer to device structure.
 * @param timeout Timeout value in microseconds.
 * @param prescaler Pointer to prescaler value.
 * @param counter Pointer to counter value.
 */
static void wwdg_stm32_convert_timeout(struct device *dev, u32_t timeout,
				       u32_t *prescaler,
				       u32_t *counter)
{
	u32_t clock_freq = wwdg_stm32_get_pclk(dev);
	u8_t divider = 0U;
	u8_t shift = 3U;

	/* Convert timeout to seconds. */
	float timeout_s = (float)timeout / USEC_PER_SEC;
	float wwdg_freq;

	*prescaler = 0;
	*counter = 0;

	for (divider = 8; divider >= 1; divider >>= 1) {
		wwdg_freq = ((float)clock_freq) / WWDG_INTERNAL_DIVIDER / divider;
		/* +1 to ceil the result, which may lose from truncation */
		*counter = (u32_t)(timeout_s * wwdg_freq + 1) - 1;
		*counter |= WWDG_RESET_LIMIT;
		*prescaler = shift << 7;

		if (*counter <= WWDG_COUNTER_MAX) {
			break;
		}

		shift--;
	}
}

static int wwdg_stm32_setup(struct device *dev, u8_t options)
{
	WWDG_TypeDef *wwdg = WWDG_STM32_STRUCT(dev);

	/* Deactivate running when debugger is attached. */
	if (options & WDT_OPT_PAUSE_HALTED_BY_DBG) {
#if defined(CONFIG_SOC_SERIES_STM32F0X)
		LL_APB1_GRP2_EnableClock(LL_APB1_GRP2_PERIPH_DBGMCU);
#elif defined(CONFIG_SOC_SERIES_STM32L0X)
		LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_DBGMCU);
#endif
		LL_DBGMCU_APB1_GRP1_FreezePeriph(LL_DBGMCU_APB1_GRP1_WWDG_STOP);
	}

	if (options & WDT_OPT_PAUSE_IN_SLEEP) {
		return -ENOTSUP;
	}

	/* Ensure that Early Wakeup Interrupt Flag is cleared */
	LL_WWDG_ClearFlag_EWKUP(wwdg);

	/* Enable the WWDG */
	LL_WWDG_Enable(wwdg);

	return 0;
}

static int wwdg_stm32_disable(struct device *dev)
{
	/* watchdog cannot be stopped once started unless SOC gets a reset */
	ARG_UNUSED(dev);

	return -EPERM;
}

static int wwdg_stm32_install_timeout(struct device *dev,
				      const struct wdt_timeout_cfg *config)
{
	struct wwdg_stm32_data *data = WWDG_STM32_DATA(dev);
	WWDG_TypeDef *wwdg = WWDG_STM32_STRUCT(dev);
	u32_t timeout = config->window.max * USEC_PER_MSEC;
	u32_t calculated_timeout;
	u32_t prescaler = 0U;
	u32_t counter = 0U;

	if (config->callback != NULL) {
		data->callback = config->callback;
	}

	wwdg_stm32_convert_timeout(dev, timeout, &prescaler, &counter);

	calculated_timeout = wwdg_stm32_get_timeout(dev, prescaler, counter);
	if (!(IS_WWDG_PRESCALER(prescaler) && IS_WWDG_COUNTER(counter) &&
	      IS_WWDG_TIMEOUT(timeout, calculated_timeout))) {
		/* One of the parameters provided is invalid */
		return -EINVAL;
	}

	data->counter = counter;

	/* Configure WWDG */
	/* Set the programmable prescaler */
	LL_WWDG_SetPrescaler(wwdg, prescaler);

	/* Set window the same as the counter to be able to feed the WWDG almost
	 * immediately
	 */
	LL_WWDG_SetWindow(wwdg, counter);
	LL_WWDG_SetCounter(wwdg, counter);

	return 0;
}

static int wwdg_stm32_feed(struct device *dev, int channel_id)
{
	WWDG_TypeDef *wwdg = WWDG_STM32_STRUCT(dev);
	struct wwdg_stm32_data *data = WWDG_STM32_DATA(dev);

	ARG_UNUSED(channel_id);
	LL_WWDG_SetCounter(wwdg, data->counter);

	return 0;
}

void wwdg_stm32_isr(void *arg)
{
	struct device *const dev = (struct device *)arg;
	struct wwdg_stm32_data *data = WWDG_STM32_DATA(dev);
	WWDG_TypeDef *wwdg = WWDG_STM32_STRUCT(dev);

	if (LL_WWDG_IsEnabledIT_EWKUP(wwdg)) {
		if (LL_WWDG_IsActiveFlag_EWKUP(wwdg)) {
			LL_WWDG_ClearFlag_EWKUP(wwdg);
			data->callback(dev, 0);
		}
	}
}

static const struct wdt_driver_api wwdg_stm32_api = {
	.setup = wwdg_stm32_setup,
	.disable = wwdg_stm32_disable,
	.install_timeout = wwdg_stm32_install_timeout,
	.feed = wwdg_stm32_feed,
};

static int wwdg_stm32_init(struct device *dev)
{
	struct device *clk = device_get_binding(STM32_CLOCK_CONTROL_NAME);
	const struct wwdg_stm32_config *cfg = WWDG_STM32_CFG(dev);

	__ASSERT_NO_MSG(clk);

	clock_control_on(clk, (clock_control_subsys_t *) &cfg->pclken);

	wwdg_stm32_irq_config(dev);

	return 0;
}

static struct wwdg_stm32_data wwdg_stm32_dev_data = {
	.counter = WWDG_RESET_LIMIT,
	.callback = NULL
};

static struct wwdg_stm32_config wwdg_stm32_dev_config = {
	.pclken = {
		.enr = DT_INST_CLOCKS_CELL(0, bits),
		.bus = DT_INST_CLOCKS_CELL(0, bus)
	},
	.Instance = (WWDG_TypeDef *)DT_INST_REG_ADDR(0),
};

DEVICE_AND_API_INIT(wwdg_stm32, DT_INST_LABEL(0),
		    wwdg_stm32_init, &wwdg_stm32_dev_data, &wwdg_stm32_dev_config,
		    POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEVICE,
		    &wwdg_stm32_api);

static void wwdg_stm32_irq_config(struct device *dev)
{
	WWDG_TypeDef *wwdg = WWDG_STM32_STRUCT(dev);

	IRQ_CONNECT(DT_INST_IRQN(0),
		    DT_INST_IRQ(0, priority),
		    wwdg_stm32_isr, DEVICE_GET(wwdg_stm32), 0);
	irq_enable(DT_INST_IRQN(0));
	LL_WWDG_EnableIT_EWKUP(wwdg);
}
