/*
 * Copyright (c) 2021 Teslabs Engineering S.L.
 *
 * SPDX-License-Identifier: Apache-2.0
 */

#define DT_DRV_COMPAT gd_gd32_pwm

#include <errno.h>

#include <drivers/pwm.h>
#include <drivers/pinctrl.h>
#include <soc.h>
#include <sys/util_macro.h>

#include <logging/log.h>
LOG_MODULE_REGISTER(pwm_gd32, CONFIG_PWM_LOG_LEVEL);

/** PWM data. */
struct pwm_gd32_data {
	/** Timer clock (Hz). */
	uint32_t tim_clk;
};

/** PWM configuration. */
struct pwm_gd32_config {
	/** Timer register. */
	uint32_t reg;
	/** Number of channels */
	uint8_t channels;
	/** Flag to indicate if timer has 32-bit counter */
	bool is_32bit;
	/** Flag to indicate if timer is advanced */
	bool is_advanced;
	/** Prescaler. */
	uint16_t prescaler;
	/** RCU peripheral clock. */
	uint32_t rcu_periph_clock;
	/** RCU peripheral reset. */
	uint32_t rcu_periph_reset;
	/** pinctrl configurations. */
	const struct pinctrl_dev_config *pcfg;
};

/** Obtain channel enable bit for the given channel */
#define TIMER_CHCTL2_CHXEN(ch) BIT(4U * (ch))
/** Obtain polarity bit for the given channel */
#define TIMER_CHCTL2_CHXP(ch) BIT(1U + (4U * (ch)))
/** Obtain CHCTL0/1 mask for the given channel (0 or 1) */
#define TIMER_CHCTLX_MSK(ch) (0xFU << (8U * (ch)))

/** Obtain RCU register offset from RCU clock value */
#define RCU_CLOCK_OFFSET(rcu_clock) ((rcu_clock) >> 6U)

/**
 * Obtain the timer clock.
 *
 * @param dev Device instance.
 *
 * @return Timer clock (Hz).
 */
static uint32_t pwm_gd32_get_tim_clk(const struct device *dev)
{
	const struct pwm_gd32_config *config = dev->config;
	uint32_t apb_psc, apb_clk;

	/* obtain APB prescaler value */
	if (RCU_CLOCK_OFFSET(config->rcu_periph_clock) == APB1EN_REG_OFFSET) {
		apb_psc = RCU_CFG0 & RCU_CFG0_APB1PSC;
	} else {
		apb_psc = RCU_CFG0 & RCU_CFG0_APB2PSC;
	}

	switch (apb_psc) {
	case RCU_APB1_CKAHB_DIV2:
		apb_psc = 2U;
		break;
	case RCU_APB1_CKAHB_DIV4:
		apb_psc = 4U;
		break;
	case RCU_APB1_CKAHB_DIV8:
		apb_psc = 8U;
		break;
	case RCU_APB1_CKAHB_DIV16:
		apb_psc = 16U;
		break;
	default:
		apb_psc = 1U;
		break;
	}

	apb_clk = CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC / apb_psc;

#ifdef RCU_CFG1_TIMERSEL
	/*
	 * The TIMERSEL bit in RCU_CFG1 controls the clock frequency of all the
	 * timers connected to the APB1 and APB2 domains.
	 *
	 * Up to a certain threshold value of APB{1,2} prescaler, timer clock
	 * equals to CK_AHB. This threshold value depends on TIMERSEL setting
	 * (2 if TIMERSEL=0, 4 if TIMERSEL=1). Above threshold, timer clock is
	 * set to a multiple of the APB domain clock CK_APB{1,2} (2 if
	 * TIMERSEL=0, 4 if TIMERSEL=1).
	 */

	/* TIMERSEL = 0 */
	if ((RCU_CFG1 & RCU_CFG1_TIMERSEL) == 0U) {
		if (apb_psc <= 2U) {
			return CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC;
		}

		return apb_clk * 2U;
	}

	/* TIMERSEL = 1 */
	if (apb_psc <= 4U) {
		return CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC;
	}

	return apb_clk * 4U;
#else
	/*
	 * If the APB prescaler equals 1, the timer clock frequencies are set to
	 * the same frequency as that of the APB domain. Otherwise, they are set
	 * to twice the frequency of the APB domain.
	 */
	if (apb_psc == 1U) {
		return apb_clk;
	}

	return apb_clk * 2U;
#endif /* RCU_CFG1_TIMERSEL */
}

static int pwm_gd32_pin_set(const struct device *dev, uint32_t pwm,
			    uint32_t period_cycles, uint32_t pulse_cycles,
			    pwm_flags_t flags)
{
	const struct pwm_gd32_config *config = dev->config;

	if (pwm >= config->channels) {
		return -EINVAL;
	}

	/* 16-bit timers can count up to UINT16_MAX */
	if (!config->is_32bit && (period_cycles > UINT16_MAX)) {
		return -ENOTSUP;
	}

	/* disable channel output if period is zero */
	if (period_cycles == 0U) {
		TIMER_CHCTL2(config->reg) &= ~TIMER_CHCTL2_CHXEN(pwm);
		return 0;
	}

	/* update polarity */
	if ((flags & PWM_POLARITY_INVERTED) != 0U) {
		TIMER_CHCTL2(config->reg) |= TIMER_CHCTL2_CHXP(pwm);
	} else {
		TIMER_CHCTL2(config->reg) &= ~TIMER_CHCTL2_CHXP(pwm);
	}

	/* update pulse */
	switch (pwm) {
	case 0U:
		TIMER_CH0CV(config->reg) = pulse_cycles;
		break;
	case 1U:
		TIMER_CH1CV(config->reg) = pulse_cycles;
		break;
	case 2U:
		TIMER_CH2CV(config->reg) = pulse_cycles;
		break;
	case 3U:
		TIMER_CH3CV(config->reg) = pulse_cycles;
		break;
	default:
		__ASSERT_NO_MSG(NULL);
		break;
	}

	/* update period */
	TIMER_CAR(config->reg) = period_cycles;

	/* channel not enabled: configure it */
	if ((TIMER_CHCTL2(config->reg) & TIMER_CHCTL2_CHXEN(pwm)) == 0U) {
		volatile uint32_t *chctl;

		/* select PWM1 mode, enable OC shadowing */
		if (pwm < 2U) {
			chctl = &TIMER_CHCTL0(config->reg);
		} else {
			chctl = &TIMER_CHCTL1(config->reg);
		}

		*chctl &= ~TIMER_CHCTLX_MSK(pwm);
		*chctl |= (TIMER_OC_MODE_PWM1 | TIMER_OC_SHADOW_ENABLE) <<
			  (8U * (pwm % 2U));

		/* enable channel output */
		TIMER_CHCTL2(config->reg) |= TIMER_CHCTL2_CHXEN(pwm);

		/* generate update event (to load shadow values) */
		TIMER_SWEVG(config->reg) |= TIMER_SWEVG_UPG;
	}

	return 0;
}

static int pwm_gd32_get_cycles_per_sec(const struct device *dev, uint32_t pwm,
				       uint64_t *cycles)
{
	struct pwm_gd32_data *data = dev->data;
	const struct pwm_gd32_config *config = dev->config;

	*cycles = (uint64_t)(data->tim_clk / (config->prescaler + 1U));

	return 0;
}

static const struct pwm_driver_api pwm_gd32_driver_api = {
	.pin_set = pwm_gd32_pin_set,
	.get_cycles_per_sec = pwm_gd32_get_cycles_per_sec,
};

static int pwm_gd32_init(const struct device *dev)
{
	const struct pwm_gd32_config *config = dev->config;
	struct pwm_gd32_data *data = dev->data;
	int ret;

	rcu_periph_clock_enable(config->rcu_periph_clock);

	/* reset timer to its default state */
	rcu_periph_reset_enable(config->rcu_periph_reset);
	rcu_periph_reset_disable(config->rcu_periph_reset);

	/* apply pin configuration */
	ret = pinctrl_apply_state(config->pcfg, PINCTRL_STATE_DEFAULT);
	if (ret < 0) {
		return ret;
	}

	/* cache timer clock value */
	data->tim_clk = pwm_gd32_get_tim_clk(dev);

	/* basic timer operation: edge aligned, up counting, shadowed CAR */
	TIMER_CTL0(config->reg) = TIMER_CKDIV_DIV1 | TIMER_COUNTER_EDGE |
				  TIMER_COUNTER_UP | TIMER_CTL0_ARSE;
	TIMER_PSC(config->reg) = config->prescaler;

	/* enable primary output for advanced timers */
	if (config->is_advanced) {
		TIMER_CCHP(config->reg) |= TIMER_CCHP_POEN;
	}

	/* enable timer counter */
	TIMER_CTL0(config->reg) |= TIMER_CTL0_CEN;

	return 0;
}

#define PWM_GD32_DEFINE(i)						       \
	static struct pwm_gd32_data pwm_gd32_data_##i;			       \
									       \
	PINCTRL_DT_INST_DEFINE(i);					       \
									       \
	static const struct pwm_gd32_config pwm_gd32_config_##i = {	       \
		.reg = DT_REG_ADDR(DT_INST_PARENT(i)),			       \
		.rcu_periph_clock = DT_PROP(DT_INST_PARENT(i),		       \
					    rcu_periph_clock),		       \
		.rcu_periph_reset = DT_PROP(DT_INST_PARENT(i),		       \
					    rcu_periph_reset),		       \
		.prescaler = DT_PROP(DT_INST_PARENT(i), prescaler),	       \
		.channels = DT_PROP(DT_INST_PARENT(i), channels),	       \
		.is_32bit = DT_PROP(DT_INST_PARENT(i), is_32bit),	       \
		.is_advanced = DT_PROP(DT_INST_PARENT(i), is_advanced),	       \
		.pcfg = PINCTRL_DT_INST_DEV_CONFIG_GET(i),		       \
	};								       \
									       \
	DEVICE_DT_INST_DEFINE(i, &pwm_gd32_init, NULL, &pwm_gd32_data_##i,     \
			      &pwm_gd32_config_##i, POST_KERNEL,	       \
			      CONFIG_KERNEL_INIT_PRIORITY_DEVICE,	       \
			      &pwm_gd32_driver_api);

DT_INST_FOREACH_STATUS_OKAY(PWM_GD32_DEFINE)
