Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 11 additions & 5 deletions boards/silabs/dev_kits/xg24_dk2601b/xg24_dk2601b.dts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@
led1 = &green_led;
led2 = &blue_led;
pwm-led0 = &red_pwm_led;
pwm-led1 = &green_pwm_led;
pwm-led2 = &blue_pwm_led;
sw0 = &button0;
sw1 = &button1;
watchdog0 = &wdog0;
Expand All @@ -52,17 +54,17 @@
compatible = "pwm-leds";

red_pwm_led: pwm_led_0 {
pwms = <&timer0 0 PWM_MSEC(20) PWM_POLARITY_INVERTED>;
pwms = <&timer0_pwm 0 PWM_MSEC(20) PWM_POLARITY_INVERTED>;
label = "red";
};

green_pwm_led: pwm_led_1 {
pwms = <&timer0 1 PWM_MSEC(20) PWM_POLARITY_INVERTED>;
pwms = <&timer0_pwm 1 PWM_MSEC(20) PWM_POLARITY_INVERTED>;
label = "green";
};

blue_pwm_led: pwm_led_2 {
pwms = <&timer0 2 PWM_MSEC(20) PWM_POLARITY_INVERTED>;
pwms = <&timer0_pwm 2 PWM_MSEC(20) PWM_POLARITY_INVERTED>;
label = "blue";
};
};
Expand Down Expand Up @@ -93,9 +95,13 @@
};

&timer0 {
pinctrl-0 = <&timer0_default>;
pinctrl-names = "default";
status = "okay";

timer0_pwm: pwm {
pinctrl-0 = <&timer0_default>;
pinctrl-names = "default";
status = "okay";
};
};

&cpu0 {
Expand Down
39 changes: 22 additions & 17 deletions drivers/pwm/pwm_silabs_letimer.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,6 @@

LOG_MODULE_REGISTER(pwm_silabs_letimer, CONFIG_PWM_LOG_LEVEL);

#define LETIMER_UFOA_MASK(channel) \
((channel == 0) ? _LETIMER_CTRL_UFOA0_MASK : _LETIMER_CTRL_UFOA1_MASK)
#define LETIMER_UFOA_PWM(channel) ((channel == 0) ? LETIMER_CTRL_UFOA0_PWM : LETIMER_CTRL_UFOA1_PWM)

struct silabs_letimer_pwm_config {
const struct pinctrl_dev_config *pcfg;
const struct device *clock_dev;
Expand All @@ -31,12 +27,20 @@ struct silabs_letimer_pwm_config {
bool run_in_debug;
};

static bool silabs_letimer_channel_is_pwm(const struct silabs_letimer_pwm_config *config,
uint32_t channel)
{
uint32_t mask = (channel == 0) ? _LETIMER_CTRL_UFOA0_MASK : _LETIMER_CTRL_UFOA1_MASK;

return FIELD_GET(mask, config->base->CTRL) == _LETIMER_CTRL_UFOA0_PWM;
}

static int silabs_letimer_pwm_set_cycles(const struct device *dev, uint32_t channel,
uint32_t period_cycles, uint32_t pulse_cycles,
pwm_flags_t flags)
{
const struct silabs_letimer_pwm_config *config = dev->config;
bool invert_polarity = (flags & PWM_POLARITY_MASK) == PWM_POLARITY_INVERTED;
const struct silabs_letimer_pwm_config *config = dev->config;

if (period_cycles >= BIT(24) || pulse_cycles >= BIT(24)) {
return -ENOTSUP;
Expand All @@ -56,8 +60,9 @@ static int silabs_letimer_pwm_set_cycles(const struct device *dev, uint32_t chan
sys_clear_bit((mem_addr_t)&config->base->CTRL, channel + _LETIMER_CTRL_OPOL0_SHIFT);
}

if (FIELD_GET(LETIMER_UFOA_MASK(channel), config->base->CTRL) != _LETIMER_CTRL_UFOA0_PWM) {
config->base->CTRL_SET = LETIMER_UFOA_PWM(channel);
if (!silabs_letimer_channel_is_pwm(config, channel)) {
config->base->CTRL_SET =
(channel == 0) ? LETIMER_CTRL_UFOA0_PWM : LETIMER_CTRL_UFOA1_PWM;
}

sl_hal_letimer_set_compare(config->base, channel, pulse_cycles);
Expand All @@ -73,9 +78,9 @@ static int silabs_letimer_pwm_set_cycles(const struct device *dev, uint32_t chan
static int silabs_letimer_pwm_get_cycles_per_sec(const struct device *dev, uint32_t channel,
uint64_t *cycles)
{
int err;
uint32_t clock_rate;
const struct silabs_letimer_pwm_config *config = dev->config;
uint32_t clock_rate;
int err;

err = clock_control_get_rate(config->clock_dev, (clock_control_subsys_t)&config->clock_cfg,
&clock_rate);
Expand All @@ -90,8 +95,8 @@ static int silabs_letimer_pwm_get_cycles_per_sec(const struct device *dev, uint3

static int silabs_letimer_pwm_pm_action(const struct device *dev, enum pm_device_action action)
{
int err;
const struct silabs_letimer_pwm_config *config = dev->config;
int err;

if (action == PM_DEVICE_ACTION_RESUME) {
err = clock_control_on(config->clock_dev,
Expand Down Expand Up @@ -128,9 +133,9 @@ static int silabs_letimer_pwm_pm_action(const struct device *dev, enum pm_device

static int silabs_letimer_pwm_init(const struct device *dev)
{
int err;
const struct silabs_letimer_pwm_config *config = dev->config;
sl_hal_letimer_config_t letimer_config = SL_HAL_LETIMER_CONFIG_DEFAULT;
const struct silabs_letimer_pwm_config *config = dev->config;
int err;

err = clock_control_on(config->clock_dev, (clock_control_subsys_t)&config->clock_cfg);
if (err < 0 && err != -EALREADY) {
Expand All @@ -156,11 +161,11 @@ static DEVICE_API(pwm, silabs_letimer_pwm_api) = {
\
static const struct silabs_letimer_pwm_config letimer_pwm_config_##inst = { \
.pcfg = PINCTRL_DT_INST_DEV_CONFIG_GET(inst), \
.clock_dev = DEVICE_DT_GET(DT_INST_CLOCKS_CTLR(inst)), \
.clock_cfg = SILABS_DT_INST_CLOCK_CFG(inst), \
.base = (LETIMER_TypeDef *)DT_INST_REG_ADDR(inst), \
.run_in_debug = DT_INST_PROP(inst, run_in_debug), \
.clock_div = DT_INST_ENUM_IDX(inst, clock_div), \
.clock_dev = DEVICE_DT_GET(DT_CLOCKS_CTLR(DT_INST_PARENT(inst))), \
.clock_cfg = SILABS_DT_CLOCK_CFG(DT_INST_PARENT(inst)), \
.base = (LETIMER_TypeDef *)DT_REG_ADDR(DT_INST_PARENT(inst)), \
.run_in_debug = DT_PROP(DT_INST_PARENT(inst), run_in_debug), \
.clock_div = DT_ENUM_IDX(DT_INST_PARENT(inst), clock_div), \
}; \
DEVICE_DT_INST_DEFINE(inst, &silabs_letimer_pwm_init, PM_DEVICE_DT_INST_GET(inst), NULL, \
&letimer_pwm_config_##inst, POST_KERNEL, CONFIG_PWM_INIT_PRIORITY, \
Expand Down
39 changes: 20 additions & 19 deletions drivers/pwm/pwm_silabs_timer.c
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,8 @@ static int silabs_timer_pwm_set_cycles(const struct device *dev, uint32_t channe
uint32_t period_cycles, uint32_t pulse_cycles,
pwm_flags_t flags)
{
const struct silabs_timer_pwm_config *config = dev->config;
bool invert_polarity = (flags & PWM_POLARITY_MASK) == PWM_POLARITY_INVERTED;
const struct silabs_timer_pwm_config *config = dev->config;

if (channel > config->num_channels) {
return -EINVAL;
Expand Down Expand Up @@ -97,9 +97,9 @@ static int silabs_timer_pwm_set_cycles(const struct device *dev, uint32_t channe
static int silabs_timer_pwm_get_cycles_per_sec(const struct device *dev, uint32_t channel,
uint64_t *cycles)
{
int err;
uint32_t clock_rate;
const struct silabs_timer_pwm_config *config = dev->config;
uint32_t clock_rate;
int err;

if (channel > config->num_channels) {
return -EINVAL;
Expand All @@ -121,10 +121,10 @@ static int silabs_timer_pwm_configure_capture(const struct device *dev, uint32_t
pwm_flags_t flags, pwm_capture_callback_handler_t cb,
void *user_data)
{
const struct silabs_timer_pwm_config *config = dev->config;
struct silabs_timer_pwm_data *data = dev->data;
sl_hal_timer_channel_config_t ch_config = SL_HAL_TIMER_CHANNEL_CONFIG_DEFAULT;
bool invert_polarity = (flags & PWM_POLARITY_MASK) == PWM_POLARITY_INVERTED;
const struct silabs_timer_pwm_config *config = dev->config;
struct silabs_timer_pwm_data *data = dev->data;

if (channel != 0) {
LOG_ERR("Only channel 0 is supported for capture");
Expand Down Expand Up @@ -226,8 +226,8 @@ static void silabs_timer_pwm_isr(const struct device *dev)
{
const struct silabs_timer_pwm_config *config = dev->config;
struct silabs_timer_pwm_data *data = dev->data;
uint32_t pulse_cycles = 0;
uint32_t period_cycles = 0;
uint32_t pulse_cycles = 0;

if (!(sl_hal_timer_get_enabled_pending_interrupts(config->base) & TIMER_IF_CC0)) {
return;
Expand Down Expand Up @@ -270,8 +270,8 @@ static void silabs_timer_pwm_isr(const struct device *dev)

static int silabs_timer_pwm_pm_action(const struct device *dev, enum pm_device_action action)
{
int err;
const struct silabs_timer_pwm_config *config = dev->config;
int err;

if (action == PM_DEVICE_ACTION_RESUME) {
err = clock_control_on(config->clock_dev,
Expand Down Expand Up @@ -316,9 +316,9 @@ static int silabs_timer_pwm_pm_action(const struct device *dev, enum pm_device_a

static int silabs_timer_pwm_init(const struct device *dev)
{
int err;
const struct silabs_timer_pwm_config *config = dev->config;
sl_hal_timer_config_t timer_config = SL_HAL_TIMER_CONFIG_DEFAULT;
const struct silabs_timer_pwm_config *config = dev->config;
int err;

err = clock_control_on(config->clock_dev, (clock_control_subsys_t)&config->clock_cfg);
if (err < 0 && err != -EALREADY) {
Expand Down Expand Up @@ -351,9 +351,10 @@ static DEVICE_API(pwm, silabs_timer_pwm_api) = {
#define TIMER_IRQ_CONFIG_HANDLER(inst) \
static void silabs_timer_pwm_irq_config_##inst(const struct device *dev) \
{ \
IRQ_CONNECT(DT_INST_IRQ(inst, irq), DT_INST_IRQ(inst, priority), \
silabs_timer_pwm_isr, DEVICE_DT_INST_GET(inst), 0); \
irq_enable(DT_INST_IRQ(inst, irq)); \
IRQ_CONNECT(DT_IRQ(DT_INST_PARENT(inst), irq), \
DT_IRQ(DT_INST_PARENT(inst), priority), silabs_timer_pwm_isr, \
DEVICE_DT_INST_GET(inst), 0); \
irq_enable(DT_IRQ(DT_INST_PARENT(inst), irq)); \
}
#else
#define TIMER_IRQ_CONFIG_FUNC(inst) NULL
Expand All @@ -367,14 +368,14 @@ static DEVICE_API(pwm, silabs_timer_pwm_api) = {
\
static const struct silabs_timer_pwm_config timer_pwm_config_##inst = { \
.pcfg = PINCTRL_DT_INST_DEV_CONFIG_GET(inst), \
.clock_dev = DEVICE_DT_GET(DT_INST_CLOCKS_CTLR(inst)), \
.clock_cfg = SILABS_DT_INST_CLOCK_CFG(inst), \
.base = (TIMER_TypeDef *)DT_INST_REG_ADDR(inst), \
.clock_dev = DEVICE_DT_GET(DT_CLOCKS_CTLR(DT_INST_PARENT(inst))), \
.clock_cfg = SILABS_DT_CLOCK_CFG(DT_INST_PARENT(inst)), \
.base = (TIMER_TypeDef *)DT_REG_ADDR(DT_INST_PARENT(inst)), \
.irq_config_func = TIMER_IRQ_CONFIG_FUNC(inst), \
.clock_div = DT_INST_PROP(inst, clock_div), \
.num_channels = DT_INST_PROP(inst, channels), \
.counter_size = DT_INST_PROP(inst, counter_size), \
.run_in_debug = DT_INST_PROP(inst, run_in_debug), \
.clock_div = DT_PROP(DT_INST_PARENT(inst), clock_div), \
.num_channels = DT_PROP(DT_INST_PARENT(inst), channels), \
.counter_size = DT_PROP(DT_INST_PARENT(inst), counter_size), \
.run_in_debug = DT_PROP(DT_INST_PARENT(inst), run_in_debug), \
}; \
static struct silabs_timer_pwm_data timer_pwm_data_##inst; \
DEVICE_DT_INST_DEFINE(inst, &silabs_timer_pwm_init, PM_DEVICE_DT_INST_GET(inst), \
Expand Down
76 changes: 53 additions & 23 deletions dts/arm/silabs/bgm24.dtsi
Original file line number Diff line number Diff line change
Expand Up @@ -276,58 +276,83 @@
};

timer0: timer@50048000 {
compatible = "silabs,timer-pwm";
compatible = "silabs,series2-timer";
reg = <0x50048000 0x4000>;
interrupts = <4 2>;
channels = <3>;
clocks = <&cmu CLOCK_TIMER0 CLOCK_BRANCH_EM01GRPACLK>;
counter-size = <32>;
channels = <3>;
#pwm-cells = <3>;
interrupts = <4 2>;
status = "disabled";

pwm {
compatible = "silabs,timer-pwm";
#pwm-cells = <3>;
status = "disabled";
};
};

timer1: timer@5004c000 {
compatible = "silabs,timer-pwm";
compatible = "silabs,series2-timer";
reg = <0x5004c000 0x4000>;
interrupts = <5 2>;
channels = <3>;
clocks = <&cmu CLOCK_TIMER1 CLOCK_BRANCH_EM01GRPACLK>;
counter-size = <32>;
channels = <3>;
#pwm-cells = <3>;
interrupts = <5 2>;
status = "disabled";

pwm {
compatible = "silabs,timer-pwm";
#pwm-cells = <3>;
status = "disabled";
};
};

timer2: timer@50050000 {
compatible = "silabs,timer-pwm";
compatible = "silabs,series2-timer";
reg = <0x50050000 0x4000>;
interrupts = <6 2>;
channels = <3>;
clocks = <&cmu CLOCK_TIMER2 CLOCK_BRANCH_EM01GRPACLK>;
counter-size = <16>;
channels = <3>;
#pwm-cells = <3>;
interrupts = <6 2>;
status = "disabled";

pwm {
compatible = "silabs,timer-pwm";
#pwm-cells = <3>;
status = "disabled";
};
};

timer3: timer@50054000 {
compatible = "silabs,timer-pwm";
compatible = "silabs,series2-timer";
reg = <0x50054000 0x4000>;
interrupts = <7 2>;
channels = <3>;
clocks = <&cmu CLOCK_TIMER3 CLOCK_BRANCH_EM01GRPACLK>;
counter-size = <16>;
channels = <3>;
#pwm-cells = <3>;
interrupts = <7 2>;
status = "disabled";

pwm {
compatible = "silabs,timer-pwm";
#pwm-cells = <3>;
status = "disabled";
};
};

timer4: timer@50058000 {
compatible = "silabs,timer-pwm";
compatible = "silabs,series2-timer";
reg = <0x50058000 0x4000>;
interrupts = <8 2>;
channels = <3>;
clocks = <&cmu CLOCK_TIMER4 CLOCK_BRANCH_EM01GRPACLK>;
counter-size = <16>;
channels = <3>;
#pwm-cells = <3>;
interrupts = <8 2>;
status = "disabled";

pwm {
compatible = "silabs,timer-pwm";
#pwm-cells = <3>;
status = "disabled";
};
};

usart0: usart@5005c000 {
Expand Down Expand Up @@ -477,12 +502,17 @@
};

letimer0: letimer@59000000 {
compatible = "silabs,letimer-pwm";
compatible = "silabs,series2-letimer";
reg = <0x59000000 0x4000>;
interrupts = <18 2>;
clocks = <&cmu CLOCK_LETIMER0 CLOCK_BRANCH_EM23GRPACLK>;
#pwm-cells = <3>;
interrupts = <18 2>;
status = "disabled";

pwm {
compatible = "silabs,letimer-pwm";
#pwm-cells = <3>;
status = "disabled";
};
};

adc0: adc@59004000 {
Expand Down
Loading
Loading