Commit 22e64fdd authored by Gerard Marull-Paretas's avatar Gerard Marull-Paretas Committed by Carles Cufi
Browse files

drivers: pwm: gd32: use clock control API

Use the clock control API to enable/get rate of timer clocks.

Signed-off-by: default avatarGerard Marull-Paretas <gerard@teslabs.com>
parent 4fcc1dae
Loading
Loading
Loading
Loading
+79 −0
Changes for drivers/clock_control/clock_control_gd32.c: 79 added lines, 0 removed lines.
Original line number Diff line number Diff line
@@ -37,6 +37,35 @@ struct clock_control_gd32_config {
	uint32_t base;
};

#if DT_COMPAT_GET_ANY_STATUS_OKAY(gd_gd32_timer)
/* timer identifiers */
#define TIMER_ID_OR_NONE(nodelabel)                                            \
	COND_CODE_1(DT_NODE_HAS_STATUS(DT_NODELABEL(nodelabel), okay),         \
		    (GD32_CLOCK_ID_BIT(                                        \
			     DT_CLOCKS_CELL(DT_NODELABEL(nodelabel), id)),),   \
		    ())

static const uint8_t timer_ids[] = {
	TIMER_ID_OR_NONE(timer0)  /* */
	TIMER_ID_OR_NONE(timer1)  /* */
	TIMER_ID_OR_NONE(timer2)  /* */
	TIMER_ID_OR_NONE(timer3)  /* */
	TIMER_ID_OR_NONE(timer4)  /* */
	TIMER_ID_OR_NONE(timer5)  /* */
	TIMER_ID_OR_NONE(timer6)  /* */
	TIMER_ID_OR_NONE(timer7)  /* */
	TIMER_ID_OR_NONE(timer8)  /* */
	TIMER_ID_OR_NONE(timer9)  /* */
	TIMER_ID_OR_NONE(timer10) /* */
	TIMER_ID_OR_NONE(timer11) /* */
	TIMER_ID_OR_NONE(timer12) /* */
	TIMER_ID_OR_NONE(timer13) /* */
	TIMER_ID_OR_NONE(timer14) /* */
	TIMER_ID_OR_NONE(timer15) /* */
	TIMER_ID_OR_NONE(timer16) /* */
};
#endif /* DT_COMPAT_GET_ANY_STATUS_OKAY(gd_gd32_timer) */

static int clock_control_gd32_on(const struct device *dev,
				 clock_control_subsys_t sys)
{
@@ -98,6 +127,56 @@ static int clock_control_gd32_get_rate(const struct device *dev,
		return -ENOTSUP;
	}

#if DT_COMPAT_GET_ANY_STATUS_OKAY(gd_gd32_timer)
	/* handle timer clocks */
	for (size_t i = 0U; i < ARRAY_SIZE(timer_ids); i++) {
		if (GD32_CLOCK_ID_BIT(id) != timer_ids[i]) {
			continue;
		}

#if defined(CONFIG_SOC_SERIES_GD32F4XX)
		uint32_t cfg1 = sys_read32(config->base + RCU_CFG1_OFFSET);

		/*
		 * 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 ((cfg1 & RCU_CFG1_TIMERSEL_MSK) == 0U) {
			if (psc <= 2U) {
				*rate = CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC;
			} else {
				*rate *= 2U;
			}
		/* TIMERSEL = 1 */
		} else {
			if (psc <= 4U) {
				*rate = CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC;
			} else {
				*rate *= 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 (psc != 1U) {
			*rate *= 2U;
		}
#endif /* CONFIG_SOC_SERIES_GD32F4XX */
	}
#endif /* DT_COMPAT_GET_ANY_STATUS_OKAY(gd_gd32_timer) */

	return 0;
}

+10 −87
Changes for drivers/pwm/pwm_gd32.c: 10 added lines, 87 removed lines.
Original line number Diff line number Diff line
@@ -8,12 +8,13 @@

#include <errno.h>

#include <zephyr/drivers/clock_control.h>
#include <zephyr/drivers/clock_control/gd32.h>
#include <zephyr/drivers/pwm.h>
#include <zephyr/drivers/pinctrl.h>
#include <zephyr/drivers/reset.h>
#include <zephyr/sys/util_macro.h>

#include <gd32_rcu.h>
#include <gd32_timer.h>

#include <zephyr/logging/log.h>
@@ -38,8 +39,8 @@ struct pwm_gd32_config {
	bool is_advanced;
	/** Prescaler. */
	uint16_t prescaler;
	/** RCU peripheral clock. */
	uint32_t rcu_periph_clock;
	/** Clock id. */
	uint16_t clkid;
	/** Reset. */
	struct reset_dt_spec reset;
	/** pinctrl configurations. */
@@ -56,86 +57,6 @@ struct pwm_gd32_config {
/** 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_set_cycles(const struct device *dev, uint32_t channel,
			      uint32_t period_cycles, uint32_t pulse_cycles,
			      pwm_flags_t flags)
@@ -233,7 +154,8 @@ static int pwm_gd32_init(const struct device *dev)
	struct pwm_gd32_data *data = dev->data;
	int ret;

	rcu_periph_clock_enable(config->rcu_periph_clock);
	(void)clock_control_on(GD32_CLOCK_CONTROLLER,
			       (clock_control_subsys_t *)&config->clkid);

	(void)reset_line_toggle_dt(&config->reset);

@@ -244,7 +166,9 @@ static int pwm_gd32_init(const struct device *dev)
	}

	/* cache timer clock value */
	data->tim_clk = pwm_gd32_get_tim_clk(dev);
	(void)clock_control_get_rate(GD32_CLOCK_CONTROLLER,
				     (clock_control_subsys_t *)&config->clkid,
				     &data->tim_clk);

	/* basic timer operation: edge aligned, up counting, shadowed CAR */
	TIMER_CTL0(config->reg) = TIMER_CKDIV_DIV1 | TIMER_COUNTER_EDGE |
@@ -269,8 +193,7 @@ static int pwm_gd32_init(const struct device *dev)
									       \
	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),		       \
		.clkid = DT_CLOCKS_CELL(DT_INST_PARENT(i), id),		       \
		.reset = RESET_DT_SPEC_GET(DT_INST_PARENT(i)),		       \
		.prescaler = DT_PROP(DT_INST_PARENT(i), prescaler),	       \
		.channels = DT_PROP(DT_INST_PARENT(i), channels),	       \
+14 −14
Changes for dts/arm/gigadevice/gd32e10x/gd32e10x.dtsi: 14 added lines, 14 removed lines.
Original line number Diff line number Diff line
@@ -224,7 +224,7 @@
			reg = <0x40012c00 0x400>;
			interrupts = <24 0>, <25 0>, <26 0>, <27 0>;
			interrupt-names = "brk", "up", "trgcom", "cc";
			rcu-periph-clock = <0x60b>;
			clocks = <&cctl GD32_CLOCK_TIMER0>;
			resets = <&rctl GD32_RESET_TIMER0>;
			is-advanced;
			channels = <4>;
@@ -242,7 +242,7 @@
			reg = <0x40000000 0x400>;
			interrupts = <28 0>;
			interrupt-names = "global";
			rcu-periph-clock = <0x700>;
			clocks = <&cctl GD32_CLOCK_TIMER1>;
			resets = <&rctl GD32_RESET_TIMER1>;
			channels = <4>;
			status = "disabled";
@@ -259,7 +259,7 @@
			reg = <0x40000400 0x400>;
			interrupts = <29 0>;
			interrupt-names = "global";
			rcu-periph-clock = <0x701>;
			clocks = <&cctl GD32_CLOCK_TIMER2>;
			resets = <&rctl GD32_RESET_TIMER2>;
			channels = <4>;
			status = "disabled";
@@ -276,7 +276,7 @@
			reg = <0x40000800 0x400>;
			interrupts = <30 0>;
			interrupt-names = "global";
			rcu-periph-clock = <0x702>;
			clocks = <&cctl GD32_CLOCK_TIMER3>;
			resets = <&rctl GD32_RESET_TIMER3>;
			channels = <4>;
			status = "disabled";
@@ -293,7 +293,7 @@
			reg = <0x40000c00 0x400>;
			interrupts = <50 0>;
			interrupt-names = "global";
			rcu-periph-clock = <0x703>;
			clocks = <&cctl GD32_CLOCK_TIMER4>;
			resets = <&rctl GD32_RESET_TIMER4>;
			channels = <4>;
			status = "disabled";
@@ -310,7 +310,7 @@
			reg = <0x40001000 0x400>;
			interrupts = <54 0>;
			interrupt-names = "global";
			rcu-periph-clock = <0x704>;
			clocks = <&cctl GD32_CLOCK_TIMER5>;
			resets = <&rctl GD32_RESET_TIMER5>;
			channels = <0>;
			status = "disabled";
@@ -321,7 +321,7 @@
			reg = <0x40001400 0x400>;
			interrupts = <55 0>;
			interrupt-names = "global";
			rcu-periph-clock = <0x705>;
			clocks = <&cctl GD32_CLOCK_TIMER6>;
			resets = <&rctl GD32_RESET_TIMER6>;
			channels = <0>;
			status = "disabled";
@@ -332,7 +332,7 @@
			reg = <0x40013400 0x400>;
			interrupts = <43 0>, <44 0>, <45 0>, <46 0>;
			interrupt-names = "brk", "up", "trgcom", "cc";
			rcu-periph-clock = <0x60d>;
			clocks = <&cctl GD32_CLOCK_TIMER7>;
			resets = <&rctl GD32_RESET_TIMER7>;
			is-advanced;
			channels = <4>;
@@ -350,7 +350,7 @@
			reg = <0x40014c00 0x400>;
			interrupts = <24 0>;
			interrupt-names = "global";
			rcu-periph-clock = <0x613>;
			clocks = <&cctl GD32_CLOCK_TIMER8>;
			resets = <&rctl GD32_RESET_TIMER8>;
			channels = <2>;
			status = "disabled";
@@ -367,7 +367,7 @@
			reg = <0x40015000 0x400>;
			interrupts = <25 0>;
			interrupt-names = "global";
			rcu-periph-clock = <0x614>;
			clocks = <&cctl GD32_CLOCK_TIMER9>;
			resets = <&rctl GD32_RESET_TIMER9>;
			channels = <1>;
			status = "disabled";
@@ -384,7 +384,7 @@
			reg = <0x40015400 0x400>;
			interrupts = <26 0>;
			interrupt-names = "global";
			rcu-periph-clock = <0x615>;
			clocks = <&cctl GD32_CLOCK_TIMER10>;
			resets = <&rctl GD32_RESET_TIMER10>;
			channels = <1>;
			status = "disabled";
@@ -401,7 +401,7 @@
			reg = <0x40001800 0x400>;
			interrupts = <43 0>;
			interrupt-names = "global";
			rcu-periph-clock = <0x706>;
			clocks = <&cctl GD32_CLOCK_TIMER11>;
			resets = <&rctl GD32_RESET_TIMER11>;
			channels = <2>;
			status = "disabled";
@@ -418,7 +418,7 @@
			reg = <0x40001c00 0x400>;
			interrupts = <44 0>;
			interrupt-names = "global";
			rcu-periph-clock = <0x707>;
			clocks = <&cctl GD32_CLOCK_TIMER12>;
			resets = <&rctl GD32_RESET_TIMER12>;
			channels = <1>;
			status = "disabled";
@@ -435,7 +435,7 @@
			reg = <0x40002000 0x400>;
			interrupts = <45 0>;
			interrupt-names = "global";
			rcu-periph-clock = <0x708>;
			clocks = <&cctl GD32_CLOCK_TIMER13>;
			resets = <&rctl GD32_RESET_TIMER13>;
			channels = <1>;
			status = "disabled";
+7 −7
Changes for dts/arm/gigadevice/gd32e50x/gd32e507xe.dtsi: 7 added lines, 7 removed lines.
Original line number Diff line number Diff line
@@ -14,7 +14,7 @@
			reg = <0x40013400 0x400>;
			interrupts = <43 0>, <44 0>, <45 0>, <46 0>;
			interrupt-names = "brk", "up", "trgcom", "cc";
			rcu-periph-clock = <0x60d>;
			clocks = <&cctl GD32_CLOCK_TIMER7>;
			resets = <&rctl GD32_RESET_TIMER7>;
			is-advanced;
			channels = <4>;
@@ -32,7 +32,7 @@
			reg = <0x40014c00 0x400>;
			interrupts = <24 0>;
			interrupt-names = "global";
			rcu-periph-clock = <0x613>;
			clocks = <&cctl GD32_CLOCK_TIMER8>;
			resets = <&rctl GD32_RESET_TIMER8>;
			channels = <2>;
			status = "disabled";
@@ -49,7 +49,7 @@
			reg = <0x40015000 0x400>;
			interrupts = <25 0>;
			interrupt-names = "global";
			rcu-periph-clock = <0x614>;
			clocks = <&cctl GD32_CLOCK_TIMER9>;
			resets = <&rctl GD32_RESET_TIMER9>;
			channels = <1>;
			status = "disabled";
@@ -66,7 +66,7 @@
			reg = <0x40015400 0x400>;
			interrupts = <26 0>;
			interrupt-names = "global";
			rcu-periph-clock = <0x615>;
			clocks = <&cctl GD32_CLOCK_TIMER10>;
			resets = <&rctl GD32_RESET_TIMER10>;
			channels = <1>;
			status = "disabled";
@@ -83,7 +83,7 @@
			reg = <0x40001800 0x400>;
			interrupts = <43 0>;
			interrupt-names = "global";
			rcu-periph-clock = <0x706>;
			clocks = <&cctl GD32_CLOCK_TIMER11>;
			resets = <&rctl GD32_RESET_TIMER11>;
			channels = <2>;
			status = "disabled";
@@ -100,7 +100,7 @@
			reg = <0x40001c00 0x400>;
			interrupts = <44 0>;
			interrupt-names = "global";
			rcu-periph-clock = <0x707>;
			clocks = <&cctl GD32_CLOCK_TIMER12>;
			resets = <&rctl GD32_RESET_TIMER12>;
			channels = <1>;
			status = "disabled";
@@ -117,7 +117,7 @@
			reg = <0x40002000 0x400>;
			interrupts = <45 0>;
			interrupt-names = "global";
			rcu-periph-clock = <0x708>;
			clocks = <&cctl GD32_CLOCK_TIMER13>;
			resets = <&rctl GD32_RESET_TIMER13>;
			channels = <1>;
			status = "disabled";
+7 −7
Changes for dts/arm/gigadevice/gd32e50x/gd32e50x.dtsi: 7 added lines, 7 removed lines.
Original line number Diff line number Diff line
@@ -274,7 +274,7 @@
			reg = <0x40012c00 0x400>;
			interrupts = <24 0>, <25 0>, <26 0>, <27 0>;
			interrupt-names = "brk", "up", "trgcom", "cc";
			rcu-periph-clock = <0x60b>;
			clocks = <&cctl GD32_CLOCK_TIMER0>;
			resets = <&rctl GD32_RESET_TIMER0>;
			is-advanced;
			channels = <4>;
@@ -292,7 +292,7 @@
			reg = <0x40000000 0x400>;
			interrupts = <28 0>;
			interrupt-names = "global";
			rcu-periph-clock = <0x700>;
			clocks = <&cctl GD32_CLOCK_TIMER1>;
			resets = <&rctl GD32_RESET_TIMER1>;
			is-32bit;
			channels = <4>;
@@ -310,7 +310,7 @@
			reg = <0x40000400 0x400>;
			interrupts = <29 0>;
			interrupt-names = "global";
			rcu-periph-clock = <0x701>;
			clocks = <&cctl GD32_CLOCK_TIMER2>;
			resets = <&rctl GD32_RESET_TIMER2>;
			channels = <4>;
			status = "disabled";
@@ -327,7 +327,7 @@
			reg = <0x40000800 0x400>;
			interrupts = <30 0>;
			interrupt-names = "global";
			rcu-periph-clock = <0x702>;
			clocks = <&cctl GD32_CLOCK_TIMER3>;
			resets = <&rctl GD32_RESET_TIMER3>;
			channels = <4>;
			status = "disabled";
@@ -344,7 +344,7 @@
			reg = <0x40000c00 0x400>;
			interrupts = <50 0>;
			interrupt-names = "global";
			rcu-periph-clock = <0x703>;
			clocks = <&cctl GD32_CLOCK_TIMER4>;
			resets = <&rctl GD32_RESET_TIMER4>;
			is-32bit;
			channels = <4>;
@@ -362,7 +362,7 @@
			reg = <0x40001000 0x400>;
			interrupts = <54 0>;
			interrupt-names = "global";
			rcu-periph-clock = <0x704>;
			clocks = <&cctl GD32_CLOCK_TIMER5>;
			resets = <&rctl GD32_RESET_TIMER5>;
			channels = <0>;
			status = "disabled";
@@ -373,7 +373,7 @@
			reg = <0x40001400 0x400>;
			interrupts = <55 0>;
			interrupt-names = "global";
			rcu-periph-clock = <0x705>;
			clocks = <&cctl GD32_CLOCK_TIMER6>;
			resets = <&rctl GD32_RESET_TIMER6>;
			channels = <0>;
			status = "disabled";
Loading