Skip to content

Commit 31f5d28

Browse files
Titan-Realtekkartben
authored andcommitted
drivers: pwm: rts5912: port pwm driver on Zephyr
Add PWM driver support for Realtek RTS5912 Signed-off-by: Titan Chen <titan.chen@realtek.com>
1 parent 29197ac commit 31f5d28

File tree

9 files changed

+265
-0
lines changed

9 files changed

+265
-0
lines changed

drivers/pwm/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
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

Lines changed: 2 additions & 0 deletions
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

Lines changed: 9 additions & 0 deletions
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

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

dts/arm/realtek/ec/rts5912.dtsi

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#include <zephyr/dt-bindings/adc/adc.h>
1010
#include <zephyr/dt-bindings/clock/rts5912_clock.h>
1111
#include <zephyr/dt-bindings/gpio/realtek-gpio.h>
12+
#include <zephyr/dt-bindings/pwm/pwm.h>
1213

1314
/ {
1415
cpus {
@@ -364,6 +365,70 @@
364365
interrupts = <192 0>;
365366
status = "disabled";
366367
};
368+
369+
pwm0: pwm@4000f000 {
370+
compatible = "realtek,rts5912-pwm";
371+
clocks = <&sccon RTS5912_SCCON_PERIPH_GRP0 PERIPH_GRP0_PWM0_CLKPWR>;
372+
reg = <0x4000f000 0x0c>;
373+
status = "disabled";
374+
#pwm-cells = <3>;
375+
};
376+
377+
pwm1: pwm@4000f00c {
378+
compatible = "realtek,rts5912-pwm";
379+
clocks = <&sccon RTS5912_SCCON_PERIPH_GRP0 PERIPH_GRP0_PWM1_CLKPWR>;
380+
reg = <0x4000f00c 0x0c>;
381+
status = "disabled";
382+
#pwm-cells = <3>;
383+
};
384+
385+
pwm2: pwm@4000f018 {
386+
compatible = "realtek,rts5912-pwm";
387+
clocks = <&sccon RTS5912_SCCON_PERIPH_GRP0 PERIPH_GRP0_PWM2_CLKPWR>;
388+
reg = <0x4000f018 0x0c>;
389+
status = "disabled";
390+
#pwm-cells = <3>;
391+
};
392+
393+
pwm3: pwm@4000f024 {
394+
compatible = "realtek,rts5912-pwm";
395+
clocks = <&sccon RTS5912_SCCON_PERIPH_GRP0 PERIPH_GRP0_PWM3_CLKPWR>;
396+
reg = <0x4000f024 0x0c>;
397+
status = "disabled";
398+
#pwm-cells = <3>;
399+
};
400+
401+
pwm4: pwm@4000f030 {
402+
compatible = "realtek,rts5912-pwm";
403+
clocks = <&sccon RTS5912_SCCON_PERIPH_GRP0 PERIPH_GRP0_PWM4_CLKPWR>;
404+
reg = <0x4000f030 0x0c>;
405+
status = "disabled";
406+
#pwm-cells = <3>;
407+
};
408+
409+
pwm5: pwm@4000f03c {
410+
compatible = "realtek,rts5912-pwm";
411+
clocks = <&sccon RTS5912_SCCON_PERIPH_GRP0 PERIPH_GRP0_PWM5_CLKPWR>;
412+
reg = <0x4000f03c 0x0c>;
413+
status = "disabled";
414+
#pwm-cells = <3>;
415+
};
416+
417+
pwm6: pwm@4000f048 {
418+
compatible = "realtek,rts5912-pwm";
419+
clocks = <&sccon RTS5912_SCCON_PERIPH_GRP0 PERIPH_GRP0_PWM6_CLKPWR>;
420+
reg = <0x4000f048 0x0c>;
421+
status = "disabled";
422+
#pwm-cells = <3>;
423+
};
424+
425+
pwm7: pwm@4000f054 {
426+
compatible = "realtek,rts5912-pwm";
427+
clocks = <&sccon RTS5912_SCCON_PERIPH_GRP0 PERIPH_GRP0_PWM7_CLKPWR>;
428+
reg = <0x4000f054 0x0c>;
429+
status = "disabled";
430+
#pwm-cells = <3>;
431+
};
367432
};
368433

369434
swj_port: swj-port {
Lines changed: 20 additions & 0 deletions
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

Lines changed: 26 additions & 0 deletions
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 */
Lines changed: 15 additions & 0 deletions
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+
};

tests/drivers/build_all/pwm/testcase.yaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,3 +57,5 @@ tests:
5757
drivers.pwm.max31790.build:
5858
platform_allow: nucleo_f429zi
5959
extra_args: DTC_OVERLAY_FILE=max31790.overlay
60+
drivers.pwm.rts5912.build:
61+
platform_allow: rts5912_evb

0 commit comments

Comments
 (0)