Skip to content

Commit d372d12

Browse files
committed
drivers: pwm: rts5912: port pwm driver on Zephyr
Add PWM driver support for Realtek RTS5912 Signed-off-by: Titan Chen <[email protected]>
1 parent 7abda99 commit d372d12

File tree

8 files changed

+266
-0
lines changed

8 files changed

+266
-0
lines changed

drivers/pwm/CMakeLists.txt

+1
Original file line numberDiff line numberDiff line change
@@ -54,3 +54,4 @@ zephyr_library_sources_ifdef(CONFIG_PWM_RENESAS_RZ_GPT pwm_renesas_rz_gpt.c)
5454
zephyr_library_sources_ifdef(CONFIG_USERSPACE pwm_handlers.c)
5555
zephyr_library_sources_ifdef(CONFIG_PWM_CAPTURE pwm_capture.c)
5656
zephyr_library_sources_ifdef(CONFIG_PWM_SHELL pwm_shell.c)
57+
zephyr_library_sources_ifdef(CONFIG_PWM_REALTEK_RTS5912 pwm_realtek_rts5912.c)

drivers/pwm/Kconfig

+2
Original file line numberDiff line numberDiff line change
@@ -122,4 +122,6 @@ source "drivers/pwm/Kconfig.fake"
122122

123123
source "drivers/pwm/Kconfig.renesas_rz"
124124

125+
source "drivers/pwm/Kconfig.rts5912"
126+
125127
endif # PWM

drivers/pwm/Kconfig.rts5912

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
# Copyright (c) 2025, Realtek, SIBG-SD7
2+
# SPDX-License-Identifier: Apache-2.0
3+
4+
config PWM_REALTEK_RTS5912
5+
bool "Realtek RTS5912 PWM Driver"
6+
default y
7+
depends on DT_HAS_REALTEK_RTS5912_PWM_ENABLED
8+
help
9+
Enable PWM driver for Realtek RTS5912 EC.

drivers/pwm/pwm_realtek_rts5912.c

+128
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
/*
2+
* Copyright (c) 2025 Realtek, SIBG-SD7
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
#define DT_DRV_COMPAT realtek_rts5912_pwm
8+
9+
#include <soc.h>
10+
#include <errno.h>
11+
#include <zephyr/device.h>
12+
#include <zephyr/drivers/pwm.h>
13+
#include <zephyr/drivers/pinctrl.h>
14+
#include <zephyr/logging/log.h>
15+
#include <zephyr/drivers/clock_control.h>
16+
#include <zephyr/drivers/clock_control/clock_control_rts5912.h>
17+
18+
#include "reg/reg_pwm.h"
19+
20+
LOG_MODULE_REGISTER(pwm, CONFIG_PWM_LOG_LEVEL);
21+
22+
#define PWM_CYCLE_PER_SEC MHZ(50)
23+
24+
struct pwm_rts5912_config {
25+
volatile struct pwm_regs *pwm_regs;
26+
uint32_t pwm_clk_grp;
27+
uint32_t pwm_clk_idx;
28+
const struct device *clk_dev;
29+
const struct pinctrl_dev_config *pcfg;
30+
};
31+
32+
static int pwm_rts5912_set_cycles(const struct device *dev, uint32_t channel,
33+
uint32_t period_cycles, uint32_t pulse_cycles, pwm_flags_t flags)
34+
{
35+
const struct pwm_rts5912_config *const pwm_config = dev->config;
36+
volatile struct pwm_regs *pwm_regs = pwm_config->pwm_regs;
37+
38+
uint32_t pwm_div, pwm_duty;
39+
40+
if (channel > 0) {
41+
return -EIO;
42+
}
43+
44+
pwm_div = period_cycles;
45+
pwm_duty = pulse_cycles;
46+
47+
pwm_regs->div = pwm_div;
48+
pwm_regs->duty = pwm_duty;
49+
50+
LOG_DBG("period_cycles=%d, pulse_cycles=%d, pwm_div=%d, pwm_duty=%d", period_cycles,
51+
pulse_cycles, pwm_div, pwm_duty);
52+
53+
if (flags == PWM_POLARITY_INVERTED) {
54+
pwm_regs->ctrl |= PWM_CTRL_INVT;
55+
}
56+
pwm_regs->ctrl |= PWM_CTRL_EN;
57+
58+
return 0;
59+
}
60+
61+
static int pwm_rts5912_get_cycles_per_sec(const struct device *dev, uint32_t channel,
62+
uint64_t *cycles)
63+
{
64+
ARG_UNUSED(dev);
65+
66+
if (channel > 0) {
67+
return -EIO;
68+
}
69+
70+
if (cycles) {
71+
*cycles = PWM_CYCLE_PER_SEC;
72+
}
73+
74+
return 0;
75+
}
76+
77+
static DEVICE_API(pwm, pwm_rts5912_driver_api) = {
78+
.set_cycles = pwm_rts5912_set_cycles,
79+
.get_cycles_per_sec = pwm_rts5912_get_cycles_per_sec,
80+
};
81+
82+
static int pwm_rts5912_init(const struct device *dev)
83+
{
84+
const struct pwm_rts5912_config *const pwm_config = dev->config;
85+
struct rts5912_sccon_subsys sccon;
86+
87+
int rc = 0;
88+
#ifdef CONFIG_PINCTRL
89+
rc = pinctrl_apply_state(pwm_config->pcfg, PINCTRL_STATE_DEFAULT);
90+
if (rc < 0) {
91+
LOG_ERR("PWM pinctrl setup failed (%d)", rc);
92+
return rc;
93+
}
94+
#endif
95+
#ifdef CONFIG_CLOCK_CONTROL
96+
if (!device_is_ready(pwm_config->clk_dev)) {
97+
return -ENODEV;
98+
}
99+
100+
sccon.clk_grp = pwm_config->pwm_clk_grp;
101+
sccon.clk_idx = pwm_config->pwm_clk_idx;
102+
rc = clock_control_on(pwm_config->clk_dev, (clock_control_subsys_t)&sccon);
103+
if (rc != 0) {
104+
return rc;
105+
}
106+
#endif
107+
return rc;
108+
}
109+
110+
#define RTS5912_PWM_PINCTRL_DEF(inst) PINCTRL_DT_INST_DEFINE(inst)
111+
112+
#define RTS5912_PWM_CONFIG(inst) \
113+
static struct pwm_rts5912_config pwm_rts5912_config_##inst = { \
114+
.pwm_regs = (struct pwm_regs *)DT_INST_REG_ADDR(inst), \
115+
.pwm_clk_grp = DT_INST_CLOCKS_CELL(inst, clk_grp), \
116+
.pwm_clk_idx = DT_INST_CLOCKS_CELL(inst, clk_idx), \
117+
.clk_dev = DEVICE_DT_GET(DT_INST_CLOCKS_CTLR(inst)), \
118+
.pcfg = PINCTRL_DT_INST_DEV_CONFIG_GET(inst), \
119+
};
120+
121+
#define RTS5912_PWM_DEVICE_INIT(index) \
122+
RTS5912_PWM_PINCTRL_DEF(index); \
123+
RTS5912_PWM_CONFIG(index); \
124+
DEVICE_DT_INST_DEFINE(index, &pwm_rts5912_init, NULL, NULL, &pwm_rts5912_config_##index, \
125+
POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEVICE, \
126+
&pwm_rts5912_driver_api);
127+
128+
DT_INST_FOREACH_STATUS_OKAY(RTS5912_PWM_DEVICE_INIT)

dts/arm/realtek/ec/rts5912.dtsi

+65
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#include <arm/armv8-m.dtsi>
99
#include <zephyr/dt-bindings/clock/rts5912_clock.h>
1010
#include <zephyr/dt-bindings/gpio/realtek-gpio.h>
11+
#include <zephyr/dt-bindings/pwm/pwm.h>
1112

1213
/ {
1314
cpus {
@@ -267,6 +268,70 @@
267268
interrupt-parent = <&nvic>;
268269
status = "disabled";
269270
};
271+
272+
pwm0: pwm@4000f000 {
273+
compatible = "realtek,rts5912-pwm";
274+
clocks = <&sccon RTS5912_SCCON_PERIPH_GRP0 PERIPH_GRP0_PWM0_CLKPWR>;
275+
reg = <0x4000f000 0x0c>;
276+
status = "disabled";
277+
#pwm-cells = <3>;
278+
};
279+
280+
pwm1: pwm@4000f00c {
281+
compatible = "realtek,rts5912-pwm";
282+
clocks = <&sccon RTS5912_SCCON_PERIPH_GRP0 PERIPH_GRP0_PWM1_CLKPWR>;
283+
reg = <0x4000f00c 0x0c>;
284+
status = "disabled";
285+
#pwm-cells = <3>;
286+
};
287+
288+
pwm2: pwm@4000f018 {
289+
compatible = "realtek,rts5912-pwm";
290+
clocks = <&sccon RTS5912_SCCON_PERIPH_GRP0 PERIPH_GRP0_PWM2_CLKPWR>;
291+
reg = <0x4000f018 0x0c>;
292+
status = "disabled";
293+
#pwm-cells = <3>;
294+
};
295+
296+
pwm3: pwm@4000f024 {
297+
compatible = "realtek,rts5912-pwm";
298+
clocks = <&sccon RTS5912_SCCON_PERIPH_GRP0 PERIPH_GRP0_PWM3_CLKPWR>;
299+
reg = <0x4000f024 0x0c>;
300+
status = "disabled";
301+
#pwm-cells = <3>;
302+
};
303+
304+
pwm4: pwm@4000f030 {
305+
compatible = "realtek,rts5912-pwm";
306+
clocks = <&sccon RTS5912_SCCON_PERIPH_GRP0 PERIPH_GRP0_PWM4_CLKPWR>;
307+
reg = <0x4000f030 0x0c>;
308+
status = "disabled";
309+
#pwm-cells = <3>;
310+
};
311+
312+
pwm5: pwm@4000f03c {
313+
compatible = "realtek,rts5912-pwm";
314+
clocks = <&sccon RTS5912_SCCON_PERIPH_GRP0 PERIPH_GRP0_PWM5_CLKPWR>;
315+
reg = <0x4000f03c 0x0c>;
316+
status = "disabled";
317+
#pwm-cells = <3>;
318+
};
319+
320+
pwm6: pwm@4000f048 {
321+
compatible = "realtek,rts5912-pwm";
322+
clocks = <&sccon RTS5912_SCCON_PERIPH_GRP0 PERIPH_GRP0_PWM6_CLKPWR>;
323+
reg = <0x4000f048 0x0c>;
324+
status = "disabled";
325+
#pwm-cells = <3>;
326+
};
327+
328+
pwm7: pwm@4000f054 {
329+
compatible = "realtek,rts5912-pwm";
330+
clocks = <&sccon RTS5912_SCCON_PERIPH_GRP0 PERIPH_GRP0_PWM7_CLKPWR>;
331+
reg = <0x4000f054 0x0c>;
332+
status = "disabled";
333+
#pwm-cells = <3>;
334+
};
270335
};
271336

272337
swj_port: swj-port {
+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
# Copyright (c) 2025, Realtek, SIBG-SD7
2+
# SPDX-License-Identifier: Apache-2.0
3+
4+
description: Realtek RTS5912 PWM
5+
6+
include: [pwm-controller.yaml, base.yaml, pinctrl-device.yaml]
7+
8+
compatible: "realtek,rts5912-pwm"
9+
10+
properties:
11+
reg:
12+
required: true
13+
14+
"#pwm-cells":
15+
const: 3
16+
17+
pwm-cells:
18+
- channel
19+
- period
20+
- flags

soc/realtek/ec/rts5912/reg/reg_pwm.h

+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
/*
2+
* Copyright (c) 2025 Realtek, SIBG-SD7
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
#ifndef ZEPHYR_SOC_REALTEK_RTS5912_REG_PWM_H
8+
#define ZEPHYR_SOC_REALTEK_RTS5912_REG_PWM_H
9+
10+
/*
11+
* @brief PWM Controller (PWM)
12+
*/
13+
14+
struct pwm_regs {
15+
uint32_t duty;
16+
uint32_t div;
17+
uint32_t ctrl;
18+
};
19+
20+
/* CTRL */
21+
#define PWM_CTRL_CLKSRC BIT(28)
22+
#define PWM_CTRL_INVT BIT(29)
23+
#define PWM_CTRL_RST BIT(30)
24+
#define PWM_CTRL_EN BIT(31)
25+
26+
#endif /* ZEPHYR_SOC_REALTEK_RTS5912_REG_PWM_H */
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
/*
2+
* Copyright (c) 2025 Realtek Corporation. All Rights Reserved.
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
/ {
8+
aliases {
9+
pwm-0 = &pwm0;
10+
};
11+
};
12+
13+
&pwm0 {
14+
status = "okay";
15+
};

0 commit comments

Comments
 (0)