/*
 * Copyright (c) 2022, Jamie McCrae
 *
 * SPDX-License-Identifier: Apache-2.0
 */

#define DT_DRV_COMPAT raspberrypi_pico_watchdog

#include <hardware/watchdog.h>
#include <hardware/structs/psm.h>
#include <zephyr/drivers/watchdog.h>
#include <zephyr/sys_clock.h>

#include <zephyr/logging/log.h>
LOG_MODULE_REGISTER(wdt_rpi_pico, CONFIG_WDT_LOG_LEVEL);

/* Maximum watchdog time is halved due to errata RP2040-E1 */
#define RPI_PICO_MAX_WDT_TIME (0xffffff / 2)
#define RPI_PICO_WDT_TIME_MULTIPLICATION_FACTOR 2

/* Watchdog requires a 1MHz clock source, divided from the crystal oscillator */
#define RPI_PICO_XTAL_FREQ_WDT_TICK_DIVISOR 1000000

struct wdt_rpi_pico_data {
	uint8_t reset_type;
	uint32_t load;
	bool enabled;
};

struct wdt_rpi_pico_config {
	uint32_t xtal_frequency;
};

static int wdt_rpi_pico_setup(const struct device *dev, uint8_t options)
{
	const struct wdt_rpi_pico_config *config = dev->config;
	struct wdt_rpi_pico_data *data = dev->data;

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

	hw_clear_bits(&watchdog_hw->ctrl, WATCHDOG_CTRL_ENABLE_BITS);

	psm_hw->wdsel = 0;

	/* TODO: Handle individual core reset when SMP support for RP2040 is added */
	if (data->reset_type == WDT_FLAG_RESET_SOC) {
		hw_set_bits(&psm_hw->wdsel, PSM_WDSEL_BITS);
	} else if (data->reset_type == WDT_FLAG_RESET_CPU_CORE) {
		hw_set_bits(&psm_hw->wdsel, PSM_WDSEL_PROC0_BITS);
	}

	if ((options & WDT_OPT_PAUSE_HALTED_BY_DBG) == 0) {
		hw_clear_bits(&watchdog_hw->ctrl,
			      (WATCHDOG_CTRL_PAUSE_JTAG_BITS | WATCHDOG_CTRL_PAUSE_DBG0_BITS |
			       WATCHDOG_CTRL_PAUSE_DBG1_BITS));
	} else {
		hw_set_bits(&watchdog_hw->ctrl,
			    (WATCHDOG_CTRL_PAUSE_JTAG_BITS | WATCHDOG_CTRL_PAUSE_DBG0_BITS |
			     WATCHDOG_CTRL_PAUSE_DBG1_BITS));
	}

	watchdog_hw->load = data->load;

	/* Zero out the scratch registers so that the module reboots at the
	 * default program counter
	 */
	watchdog_hw->scratch[4] = 0;
	watchdog_hw->scratch[5] = 0;
	watchdog_hw->scratch[6] = 0;
	watchdog_hw->scratch[7] = 0;

	hw_set_bits(&watchdog_hw->ctrl, WATCHDOG_CTRL_ENABLE_BITS);

	data->enabled = true;

	watchdog_hw->tick = (config->xtal_frequency / RPI_PICO_XTAL_FREQ_WDT_TICK_DIVISOR) |
			    WATCHDOG_TICK_ENABLE_BITS;

	return 0;
}

static int wdt_rpi_pico_disable(const struct device *dev)
{
	struct wdt_rpi_pico_data *data = dev->data;

	if (data->enabled == false) {
		return -EFAULT;
	}

	hw_clear_bits(&watchdog_hw->ctrl, WATCHDOG_CTRL_ENABLE_BITS);

	data->enabled = false;

	return 0;
}

static int wdt_rpi_pico_install_timeout(const struct device *dev, const struct wdt_timeout_cfg *cfg)
{
	struct wdt_rpi_pico_data *data = dev->data;

	if (cfg->window.min != 0U || cfg->window.max == 0U) {
		return -EINVAL;
	} else if (cfg->window.max * USEC_PER_MSEC > RPI_PICO_MAX_WDT_TIME) {
		return -EINVAL;
	} else if (cfg->callback != NULL) {
		return -ENOTSUP;
	} else if ((cfg->flags & WDT_FLAG_RESET_MASK) == WDT_FLAG_RESET_NONE) {
		/* The RP2040 does technically support this mode, but requires
		 * a program counter and stack pointer value to be set,
		 * therefore do not allow configuring in this mode
		 */
		return -EINVAL;
	}

	data->load = (cfg->window.max * USEC_PER_MSEC * RPI_PICO_WDT_TIME_MULTIPLICATION_FACTOR);
	data->reset_type = (cfg->flags & WDT_FLAG_RESET_MASK);

	return 0;
}

static int wdt_rpi_pico_feed(const struct device *dev, int channel_id)
{
	struct wdt_rpi_pico_data *data = dev->data;

	if (channel_id != 0) {
		/* There is only one input to the watchdog */
		return -EINVAL;
	}

	if (data->enabled == false) {
		/* Watchdog is not running so does not need to be fed */
		return -EINVAL;
	}

	watchdog_hw->load = data->load;

	return 0;
}

static int wdt_rpi_pico_init(const struct device *dev)
{
#ifndef CONFIG_WDT_DISABLE_AT_BOOT
	return wdt_rpi_pico_setup(dev, WDT_OPT_PAUSE_HALTED_BY_DBG);
#endif

	return 0;
}

static const struct wdt_driver_api wdt_rpi_pico_driver_api = {
	.setup = wdt_rpi_pico_setup,
	.disable = wdt_rpi_pico_disable,
	.install_timeout = wdt_rpi_pico_install_timeout,
	.feed = wdt_rpi_pico_feed,
};

#define WDT_RPI_PICO_WDT_DEVICE(idx)                                                               \
	static const struct wdt_rpi_pico_config wdt_##idx##_config = {                             \
		.xtal_frequency = DT_INST_PROP_BY_PHANDLE(idx, clocks, clock_frequency)            \
	};                                                                                         \
	static struct wdt_rpi_pico_data wdt_##idx##_data = {                                       \
		.reset_type = WDT_FLAG_RESET_SOC,                                                  \
		.load = (CONFIG_WDT_RPI_PICO_INITIAL_TIMEOUT *                                     \
			 RPI_PICO_WDT_TIME_MULTIPLICATION_FACTOR),                                 \
		.enabled = false                                                                   \
	};                                                                                         \
	DEVICE_DT_DEFINE(DT_NODELABEL(wdt##idx), wdt_rpi_pico_init, NULL, &wdt_##idx##_data,       \
			 &wdt_##idx##_config, PRE_KERNEL_1, CONFIG_KERNEL_INIT_PRIORITY_DEVICE,    \
			 &wdt_rpi_pico_driver_api)

DT_INST_FOREACH_STATUS_OKAY(WDT_RPI_PICO_WDT_DEVICE);
