/*
 * Copyright (c) 2017 Google LLC.
 *
 * SPDX-License-Identifier: Apache-2.0
 */

#include <soc.h>
#include <watchdog.h>

#define WDT_REGS ((Wdt *)CONFIG_WDT_SAM0_BASE_ADDRESS)

struct wdt_sam0_dev_data {
	void (*cb)(struct device *dev);
};

static struct device DEVICE_NAME_GET(wdt_sam0);

static void wdt_sam0_wait_synchronization(void)
{
	while (WDT_REGS->STATUS.bit.SYNCBUSY) {
	}
}

static void wdt_sam0_isr(struct device *dev)
{
	struct wdt_sam0_dev_data *data = dev->driver_data;

	WDT_REGS->INTFLAG.reg = WDT_INTFLAG_EW;
	if (data->cb != NULL) {
		data->cb(dev);
	}
}

static void wdt_sam0_enable(struct device *dev)
{
	WDT_REGS->CTRL.reg = WDT_CTRL_ENABLE;
	wdt_sam0_wait_synchronization();
}

static void wdt_sam0_disable(struct device *dev)
{
	WDT_REGS->CTRL.reg = 0;
	wdt_sam0_wait_synchronization();
}

static int wdt_sam0_set_config(struct device *dev, struct wdt_config *config)
{
	struct wdt_sam0_dev_data *data = dev->driver_data;
	WDT_CTRL_Type ctrl = WDT_REGS->CTRL;
	int divisor;

	/* As per wdt_esp32.c, the Zephyr watchdog API is modeled
	 * after the Quark MCU where:
	 *
	 *  timeout_ms = 2**(config->timeout + 11) / 1000
	 *
	 * The SAM0 is also power-of-two based with a 1 kHz clock, so
	 *  2**14 / 1kHz ~= 2**29 / 32 MHz.
	 */
	divisor = config->timeout + WDT_CONFIG_PER_16K_Val - WDT_2_29_CYCLES;

	/* Limit to 16x so that 8x is available for early warning. */
	if (divisor < WDT_CONFIG_PER_16_Val) {
		return -EINVAL;
	} else if (divisor > WDT_CONFIG_PER_16K_Val) {
		return -EINVAL;
	}

	/* Disable the WDT to change the config. */
	wdt_sam0_disable(dev);

	switch (config->mode) {
	case WDT_MODE_RESET:
		WDT_REGS->INTENCLR.reg = WDT_INTENCLR_EW;
		wdt_sam0_wait_synchronization();
		break;

	case WDT_MODE_INTERRUPT_RESET:
		/* Fire the early warning earlier. */
		WDT_REGS->EWCTRL.bit.EWOFFSET = divisor - 1;
		wdt_sam0_wait_synchronization();

		/* Clear the pending interrupt, if any. */
		WDT_REGS->INTFLAG.reg = WDT_INTFLAG_EW;
		wdt_sam0_wait_synchronization();

		WDT_REGS->INTENSET.reg = WDT_INTENSET_EW;
		wdt_sam0_wait_synchronization();
		break;

	default:
		return -EINVAL;
	}

	WDT_REGS->CONFIG.bit.PER = divisor;
	wdt_sam0_wait_synchronization();

	data->cb = config->interrupt_fn;

	WDT_REGS->CTRL = ctrl;
	wdt_sam0_wait_synchronization();

	return 0;
}

static void wdt_sam0_get_config(struct device *dev, struct wdt_config *config)
{
	struct wdt_sam0_dev_data *data = dev->driver_data;

	if (WDT_REGS->INTENSET.bit.EW) {
		config->mode = WDT_MODE_INTERRUPT_RESET;
	} else {
		config->mode = WDT_MODE_RESET;
	}

	config->timeout = WDT_REGS->CONFIG.bit.PER
		+ WDT_2_29_CYCLES - WDT_CONFIG_PER_16K_Val;
	config->interrupt_fn = data->cb;
}

static void wdt_sam0_reload(struct device *dev)
{
	WDT_REGS->CLEAR.bit.CLEAR = WDT_CLEAR_CLEAR_KEY_Val;
}

static const struct wdt_driver_api wdt_sam0_api = {
	.enable = wdt_sam0_enable,
	.disable = wdt_sam0_disable,
	.get_config = wdt_sam0_get_config,
	.set_config = wdt_sam0_set_config,
	.reload = wdt_sam0_reload,
};

static int wdt_sam0_init(struct device *dev)
{
	/* Enable APB clock */
	PM->APBAMASK.bit.WDT_ = 1;

	/* Connect to GCLK2 (~1 kHz) */
	GCLK->CLKCTRL.reg = GCLK_CLKCTRL_ID_WDT
		| GCLK_CLKCTRL_GEN_GCLK2
		| GCLK_CLKCTRL_CLKEN;

	IRQ_CONNECT(CONFIG_WDT_SAM0_IRQ,
		    CONFIG_WDT_SAM0_IRQ_PRIORITY, wdt_sam0_isr,
		    DEVICE_GET(wdt_sam0), 0);
	irq_enable(CONFIG_WDT_SAM0_IRQ);

	return 0;
}

static struct wdt_sam0_dev_data wdt_sam0_data;

DEVICE_AND_API_INIT(wdt_sam0, CONFIG_WDT_SAM0_LABEL, wdt_sam0_init,
		    &wdt_sam0_data, NULL, PRE_KERNEL_1,
		    CONFIG_KERNEL_INIT_PRIORITY_DEVICE, &wdt_sam0_api);
