Skip to content

Commit f3cc34c

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 9757ffa commit f3cc34c

File tree

7 files changed

+274
-0
lines changed

7 files changed

+274
-0
lines changed

drivers/pwm/CMakeLists.txt

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

drivers/pwm/Kconfig

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

121121
source "drivers/pwm/Kconfig.renesas_rz"
122122

123+
source "drivers/pwm/Kconfig.rts5912"
124+
123125
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+
uint32_t pwm_base;
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+
PWM_Type *pwm_reg = (PWM_Type *)pwm_config->pwm_base;
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_reg->DIV = pwm_div;
48+
pwm_reg->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_reg->CTRL |= PWM_CTRL_INVT_Msk;
55+
}
56+
pwm_reg->CTRL |= PWM_CTRL_EN_Msk;
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+
#if defined(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+
#if defined(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_base = DT_INST_REG_ADDR(inst), \
115+
.pwm_clk_grp = DT_INST_CLOCKS_CELL_BY_NAME(inst, pwm, clk_grp), \
116+
.pwm_clk_idx = DT_INST_CLOCKS_CELL_BY_NAME(inst, pwm, 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

+73
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 {
@@ -233,6 +234,78 @@
233234
140 0 141 0 142 0 143 0>;
234235
};
235236
};
237+
238+
pwm0: pwm@4000f000 {
239+
compatible = "realtek,rts5912-pwm";
240+
clocks = <&sccon RTS5912_SCCON_PERIPH_GRP0 PERIPH_GRP0_PWM0_CLKPWR>;
241+
clock-names = "pwm";
242+
reg = <0x4000f000 0x0c>;
243+
status = "disabled";
244+
#pwm-cells = <3>;
245+
};
246+
247+
pwm1: pwm@4000f00c {
248+
compatible = "realtek,rts5912-pwm";
249+
clocks = <&sccon RTS5912_SCCON_PERIPH_GRP0 PERIPH_GRP0_PWM1_CLKPWR>;
250+
clock-names = "pwm";
251+
reg = <0x4000f00c 0x0c>;
252+
status = "disabled";
253+
#pwm-cells = <3>;
254+
};
255+
256+
pwm2: pwm@4000f018 {
257+
compatible = "realtek,rts5912-pwm";
258+
clocks = <&sccon RTS5912_SCCON_PERIPH_GRP0 PERIPH_GRP0_PWM2_CLKPWR>;
259+
clock-names = "pwm";
260+
reg = <0x4000f018 0x0c>;
261+
status = "disabled";
262+
#pwm-cells = <3>;
263+
};
264+
265+
pwm3: pwm@4000f024 {
266+
compatible = "realtek,rts5912-pwm";
267+
clocks = <&sccon RTS5912_SCCON_PERIPH_GRP0 PERIPH_GRP0_PWM3_CLKPWR>;
268+
clock-names = "pwm";
269+
reg = <0x4000f024 0x0c>;
270+
status = "disabled";
271+
#pwm-cells = <3>;
272+
};
273+
274+
pwm4: pwm@4000f030 {
275+
compatible = "realtek,rts5912-pwm";
276+
clocks = <&sccon RTS5912_SCCON_PERIPH_GRP0 PERIPH_GRP0_PWM4_CLKPWR>;
277+
clock-names = "pwm";
278+
reg = <0x4000f030 0x0c>;
279+
status = "disabled";
280+
#pwm-cells = <3>;
281+
};
282+
283+
pwm5: pwm@4000f03c {
284+
compatible = "realtek,rts5912-pwm";
285+
clocks = <&sccon RTS5912_SCCON_PERIPH_GRP0 PERIPH_GRP0_PWM5_CLKPWR>;
286+
clock-names = "pwm";
287+
reg = <0x4000f03c 0x0c>;
288+
status = "disabled";
289+
#pwm-cells = <3>;
290+
};
291+
292+
pwm6: pwm@4000f048 {
293+
compatible = "realtek,rts5912-pwm";
294+
clocks = <&sccon RTS5912_SCCON_PERIPH_GRP0 PERIPH_GRP0_PWM6_CLKPWR>;
295+
clock-names = "pwm";
296+
reg = <0x4000f048 0x0c>;
297+
status = "disabled";
298+
#pwm-cells = <3>;
299+
};
300+
301+
pwm7: pwm@4000f054 {
302+
compatible = "realtek,rts5912-pwm";
303+
clocks = <&sccon RTS5912_SCCON_PERIPH_GRP0 PERIPH_GRP0_PWM7_CLKPWR>;
304+
clock-names = "pwm";
305+
reg = <0x4000f054 0x0c>;
306+
status = "disabled";
307+
#pwm-cells = <3>;
308+
};
236309
};
237310

238311
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

+41
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
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+
typedef struct {
15+
volatile uint32_t DUTY;
16+
volatile uint32_t DIV;
17+
18+
union {
19+
volatile uint32_t CTRL;
20+
21+
struct {
22+
uint32_t: 28;
23+
volatile uint32_t CLKSRC: 1;
24+
volatile uint32_t INVT: 1;
25+
volatile uint32_t RST: 1;
26+
volatile uint32_t EN: 1;
27+
} CTRL_b;
28+
};
29+
} PWM_Type;
30+
31+
/* CTRL */
32+
#define PWM_CTRL_CLKSRC_Pos (28UL)
33+
#define PWM_CTRL_CLKSRC_Msk BIT(28)
34+
#define PWM_CTRL_INVT_Pos (29UL)
35+
#define PWM_CTRL_INVT_Msk BIT(29)
36+
#define PWM_CTRL_RST_Pos (30UL)
37+
#define PWM_CTRL_RST_Msk BIT(30)
38+
#define PWM_CTRL_EN_Pos (31UL)
39+
#define PWM_CTRL_EN_Msk BIT(31)
40+
41+
#endif /* ZEPHYR_SOC_REALTEK_RTS5912_REG_PWM_H */

0 commit comments

Comments
 (0)