Skip to content

Commit 3d97669

Browse files
[nrf fromlist] drivers: pwm: nrfx: add global hsfll request for fast PWM
Added clock control api for global hsfll used in fast PWM120 driver. Upstream PR #: 82133 Signed-off-by: Michał Stasiak <[email protected]>
1 parent 9023a99 commit 3d97669

File tree

1 file changed

+85
-8
lines changed

1 file changed

+85
-8
lines changed

drivers/pwm/pwm_nrfx.c

Lines changed: 85 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#include <zephyr/linker/devicetree_regions.h>
1414
#include <zephyr/cache.h>
1515
#include <zephyr/mem_mgmt/mem_attr.h>
16+
#include <zephyr/drivers/clock_control/nrf_clock_control.h>
1617
#ifdef CONFIG_SOC_NRF54H20_GPD
1718
#include <nrf/gpd.h>
1819
#endif
@@ -35,6 +36,21 @@ LOG_MODULE_REGISTER(pwm_nrfx, CONFIG_PWM_LOG_LEVEL);
3536
#define ANOMALY_109_EGU_IRQ_CONNECT(idx)
3637
#endif
3738

39+
#define PWM(dev_idx) DT_NODELABEL(pwm##dev_idx)
40+
#define PWM_PROP(dev_idx, prop) DT_PROP(PWM(dev_idx), prop)
41+
#define PWM_HAS_PROP(idx, prop) DT_NODE_HAS_PROP(PWM(idx), prop)
42+
43+
#define PWM_NRFX_IS_FAST(unused, prefix, idx, _) \
44+
COND_CODE_1(DT_NODE_HAS_STATUS_OKAY(PWM(idx)), \
45+
(COND_CODE_1(PWM_HAS_PROP(idx, power_domains), \
46+
(IS_EQ(DT_PHA(PWM(idx), power_domains, id), NRF_GPD_FAST_ACTIVE1)), \
47+
(0))), (0))
48+
49+
#if (NRFX_FOREACH_PRESENT(PWM, PWM_NRFX_IS_FAST, (||), (0))) && \
50+
CONFIG_CLOCK_CONTROL_NRF2_GLOBAL_HSFLL
51+
#define PWM_NRFX_USE_CLOCK_CONTROL 1
52+
#endif
53+
3854
#define PWM_NRFX_CH_POLARITY_MASK BIT(15)
3955
#define PWM_NRFX_CH_COMPARE_MASK BIT_MASK(15)
4056
#define PWM_NRFX_CH_VALUE(compare_value, inverted) \
@@ -49,6 +65,10 @@ struct pwm_nrfx_config {
4965
#ifdef CONFIG_DCACHE
5066
uint32_t mem_attr;
5167
#endif
68+
#ifdef PWM_NRFX_USE_CLOCK_CONTROL
69+
const struct device *clk_dev;
70+
struct nrf_clock_spec clk_spec;
71+
#endif
5272
};
5373

5474
struct pwm_nrfx_data {
@@ -57,6 +77,9 @@ struct pwm_nrfx_data {
5777
uint8_t pwm_needed;
5878
uint8_t prescaler;
5979
bool stop_requested;
80+
#ifdef PWM_NRFX_USE_CLOCK_CONTROL
81+
bool clock_requested;
82+
#endif
6083
};
6184
/* Ensure the pwm_needed bit mask can accommodate all available channels. */
6285
#if (NRF_PWM_CHANNEL_COUNT > 8)
@@ -229,6 +252,18 @@ static int pwm_nrfx_set_cycles(const struct device *dev, uint32_t channel,
229252
* ensure it is stopped before starting the next playback.
230253
*/
231254
nrfx_pwm_stop(&config->pwm, false);
255+
#if PWM_NRFX_USE_CLOCK_CONTROL
256+
if (data->clock_requested && config->clk_dev) {
257+
int ret = nrf_clock_control_release(config->clk_dev, &config->clk_spec);
258+
259+
if (ret < 0) {
260+
LOG_ERR("Global HSFLL release failed: %d", ret);
261+
return ret;
262+
}
263+
264+
data->clock_requested = false;
265+
}
266+
#endif
232267
data->stop_requested = true;
233268
} else {
234269
if (data->stop_requested) {
@@ -248,6 +283,20 @@ static int pwm_nrfx_set_cycles(const struct device *dev, uint32_t channel,
248283
* until another playback is requested (new values will be
249284
* loaded then) or the PWM peripheral is stopped.
250285
*/
286+
#if PWM_NRFX_USE_CLOCK_CONTROL
287+
if (!data->clock_requested && config->clk_dev) {
288+
int ret = nrf_clock_control_request_sync(config->clk_dev,
289+
&config->clk_spec,
290+
K_FOREVER);
291+
292+
if (ret < 0) {
293+
LOG_ERR("Global HSFLL request failed: %d", ret);
294+
return ret;
295+
}
296+
297+
data->clock_requested = true;
298+
}
299+
#endif
251300
nrfx_pwm_simple_playback(&config->pwm, &config->seq, 1,
252301
NRFX_PWM_FLAG_NO_EVT_FINISHED);
253302
}
@@ -270,7 +319,7 @@ static const struct pwm_driver_api pwm_nrfx_drv_api_funcs = {
270319
.get_cycles_per_sec = pwm_nrfx_get_cycles_per_sec,
271320
};
272321

273-
static void pwm_resume(const struct device *dev)
322+
static int pwm_resume(const struct device *dev)
274323
{
275324
const struct pwm_nrfx_config *config = dev->config;
276325
uint8_t initially_inverted = 0;
@@ -299,13 +348,29 @@ static void pwm_resume(const struct device *dev)
299348

300349
seq_values_ptr_get(dev)[i] = PWM_NRFX_CH_VALUE(0, inverted);
301350
}
351+
352+
return 0;
302353
}
303354

304-
static void pwm_suspend(const struct device *dev)
355+
static int pwm_suspend(const struct device *dev)
305356
{
306357
const struct pwm_nrfx_config *config = dev->config;
307358

308359
nrfx_pwm_stop(&config->pwm, false);
360+
#if PWM_NRFX_USE_CLOCK_CONTROL
361+
struct pwm_nrfx_data *data = dev->data;
362+
363+
if (data->clock_requested) {
364+
int ret = nrf_clock_control_release(config->clk_dev, &config->clk_spec);
365+
366+
if (ret < 0) {
367+
LOG_ERR("Global HSFLL release failed: %d", ret);
368+
return ret;
369+
}
370+
371+
data->clock_requested = false;
372+
}
373+
#endif
309374
while (!nrfx_pwm_stopped_check(&config->pwm)) {
310375
}
311376

@@ -315,15 +380,17 @@ static void pwm_suspend(const struct device *dev)
315380

316381
memset(dev->data, 0, sizeof(struct pwm_nrfx_data));
317382
(void)pinctrl_apply_state(config->pcfg, PINCTRL_STATE_SLEEP);
383+
384+
return 0;
318385
}
319386

320387
static int pwm_nrfx_pm_action(const struct device *dev,
321388
enum pm_device_action action)
322389
{
323390
if (action == PM_DEVICE_ACTION_RESUME) {
324-
pwm_resume(dev);
391+
return pwm_resume(dev);
325392
} else if (IS_ENABLED(CONFIG_PM_DEVICE) && (action == PM_DEVICE_ACTION_SUSPEND)) {
326-
pwm_suspend(dev);
393+
return pwm_suspend(dev);
327394
} else {
328395
return -ENOTSUP;
329396
}
@@ -351,9 +418,6 @@ static int pwm_nrfx_init(const struct device *dev)
351418
return pm_device_driver_init(dev, pwm_nrfx_pm_action);
352419
}
353420

354-
#define PWM(dev_idx) DT_NODELABEL(pwm##dev_idx)
355-
#define PWM_PROP(dev_idx, prop) DT_PROP(PWM(dev_idx), prop)
356-
#define PWM_HAS_PROP(idx, prop) DT_NODE_HAS_PROP(PWM(idx), prop)
357421
#define PWM_MEM_REGION(idx) DT_PHANDLE(PWM(idx), memory_regions)
358422

359423
#define PWM_MEMORY_SECTION(idx) \
@@ -366,6 +430,11 @@ static int pwm_nrfx_init(const struct device *dev)
366430
COND_CODE_1(PWM_HAS_PROP(idx, memory_regions), \
367431
(DT_PROP_OR(PWM_MEM_REGION(idx), zephyr_memory_attr, 0)), (0))
368432

433+
#define PWM_INIT_PRIORITY(idx) \
434+
COND_CODE_1(PWM_NRFX_IS_FAST(_, /*empty*/, idx, _), \
435+
(UTIL_INC(CONFIG_CLOCK_CONTROL_NRF2_GLOBAL_HSFLL_INIT_PRIORITY)), \
436+
(CONFIG_PWM_INIT_PRIORITY))
437+
369438
#define PWM_NRFX_DEVICE(idx) \
370439
NRF_DT_CHECK_NODE_HAS_PINCTRL_SLEEP(PWM(idx)); \
371440
static struct pwm_nrfx_data pwm_nrfx_##idx##_data; \
@@ -393,6 +462,14 @@ static int pwm_nrfx_init(const struct device *dev)
393462
(16ul * 1000ul * 1000ul)), \
394463
IF_ENABLED(CONFIG_DCACHE, \
395464
(.mem_attr = PWM_GET_MEM_ATTR(idx),)) \
465+
IF_ENABLED(PWM_NRFX_USE_CLOCK_CONTROL, \
466+
(.clk_dev = PWM_NRFX_IS_FAST(_, /*empty*/, idx, _) \
467+
? DEVICE_DT_GET(DT_CLOCKS_CTLR(PWM(idx))) \
468+
: NULL, \
469+
.clk_spec = { \
470+
.frequency = \
471+
NRF_PERIPH_GET_FREQUENCY(PWM(idx)), \
472+
},)) \
396473
}; \
397474
static int pwm_nrfx_init##idx(const struct device *dev) \
398475
{ \
@@ -405,7 +482,7 @@ static int pwm_nrfx_init(const struct device *dev)
405482
pwm_nrfx_init##idx, PM_DEVICE_DT_GET(PWM(idx)), \
406483
&pwm_nrfx_##idx##_data, \
407484
&pwm_nrfx_##idx##_config, \
408-
POST_KERNEL, CONFIG_PWM_INIT_PRIORITY, \
485+
POST_KERNEL, PWM_INIT_PRIORITY(idx), \
409486
&pwm_nrfx_drv_api_funcs)
410487

411488
#define COND_PWM_NRFX_DEVICE(unused, prefix, i, _) \

0 commit comments

Comments
 (0)