Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[nrf fromlist] drivers: pwm: fixes for fast PWM120 #2415

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
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
69 changes: 42 additions & 27 deletions drivers/pwm/pwm_nrfx.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,7 @@
#include <zephyr/linker/devicetree_regions.h>
#include <zephyr/cache.h>
#include <zephyr/mem_mgmt/mem_attr.h>
#ifdef CONFIG_CLOCK_CONTROL
#include <zephyr/drivers/clock_control/nrf_clock_control.h>
#endif
#ifdef CONFIG_SOC_NRF54H20_GPD
#include <nrf/gpd.h>
#endif
Expand Down Expand Up @@ -48,15 +46,10 @@
(IS_EQ(DT_PHA(PWM(idx), power_domains, id), NRF_GPD_FAST_ACTIVE1)), \
(0))), (0))

#if NRFX_FOREACH_PRESENT(PWM, PWM_NRFX_IS_FAST, (||), (0))
#if CONFIG_CLOCK_CONTROL
#if (NRFX_FOREACH_PRESENT(PWM, PWM_NRFX_IS_FAST, (||), (0))) && \
CONFIG_CLOCK_CONTROL_NRF2_GLOBAL_HSFLL

Check notice on line 50 in drivers/pwm/pwm_nrfx.c

View workflow job for this annotation

GitHub Actions / Run compliance checks on patch series (PR)

You may want to run clang-format on this change

drivers/pwm/pwm_nrfx.c:50 -#if (NRFX_FOREACH_PRESENT(PWM, PWM_NRFX_IS_FAST, (||), (0))) && \ +#if (NRFX_FOREACH_PRESENT(PWM, PWM_NRFX_IS_FAST, (||), (0))) && \
#define PWM_NRFX_USE_CLOCK_CONTROL 1
#endif
#define PWM_NRFX_INIT_PRIORITY 99
#else
#define PWM_NRFX_INIT_PRIORITY CONFIG_PWM_INIT_PRIORITY
#endif


#define PWM_NRFX_CH_POLARITY_MASK BIT(15)
#define PWM_NRFX_CH_COMPARE_MASK BIT_MASK(15)
Expand Down Expand Up @@ -240,7 +233,13 @@
out_level ^= 1;
}

#if NRF_PWM_HAS_IDLEOUT
nrfx_pwm_stop(&config->pwm, true);
nrfy_pwm_channel_idle_set(config->pwm.p_reg, channel, out_level);
nrfy_pwm_enable(config->pwm.p_reg);
#else
nrf_gpio_pin_write(psel, out_level);
#endif
}

data->pwm_needed &= ~BIT(channel);
Expand All @@ -260,7 +259,7 @@
*/
nrfx_pwm_stop(&config->pwm, false);
#if PWM_NRFX_USE_CLOCK_CONTROL
if (data->clock_requested) {
if (data->clock_requested && config->clk_dev) {
int ret = nrf_clock_control_release(config->clk_dev, &config->clk_spec);

if (ret < 0) {
Expand Down Expand Up @@ -291,16 +290,18 @@
* loaded then) or the PWM peripheral is stopped.
*/
#if PWM_NRFX_USE_CLOCK_CONTROL
if (!data->clock_requested && config->clk_dev) {
int ret = nrf_clock_control_request_sync(config->clk_dev,
&config->clk_spec,
K_FOREVER);

Check notice on line 296 in drivers/pwm/pwm_nrfx.c

View workflow job for this annotation

GitHub Actions / Run compliance checks on patch series (PR)

You may want to run clang-format on this change

drivers/pwm/pwm_nrfx.c:296 - int ret = nrf_clock_control_request_sync(config->clk_dev, - &config->clk_spec, + int ret = nrf_clock_control_request_sync(config->clk_dev, &config->clk_spec,

int ret = nrf_clock_control_request_sync(config->clk_dev, &config->clk_spec,
K_FOREVER);
if (ret < 0) {
LOG_ERR("Global HSFLL request failed: %d", ret);
return ret;
}

if (ret < 0) {
LOG_ERR("Global HSFLL request failed: %d", ret);
return ret;
data->clock_requested = true;
}

data->clock_requested = true;
#endif
nrfx_pwm_simple_playback(&config->pwm, &config->seq, 1,
NRFX_PWM_FLAG_NO_EVT_FINISHED);
Expand All @@ -324,7 +325,7 @@
.get_cycles_per_sec = pwm_nrfx_get_cycles_per_sec,
};

static void pwm_resume(const struct device *dev)
static int pwm_resume(const struct device *dev)
{
const struct pwm_nrfx_config *config = dev->config;
uint8_t initially_inverted = 0;
Expand Down Expand Up @@ -353,20 +354,28 @@

seq_values_ptr_get(dev)[i] = PWM_NRFX_CH_VALUE(0, inverted);
}

return 0;
}

static void pwm_suspend(const struct device *dev)
static int pwm_suspend(const struct device *dev)
{
const struct pwm_nrfx_config *config = dev->config;

nrfx_pwm_stop(&config->pwm, false);
#if PWM_NRFX_USE_CLOCK_CONTROL
struct pwm_nrfx_data *data = dev->data;

if (data->clock_requested) {
int ret = nrf_clock_control_release(config->clk_dev, &config->clk_spec);

if (ret < 0) {
LOG_ERR("Global HSFLL release failed: %d", ret);
return ret;
}

data->clock_requested = false;
}
#endif
while (!nrfx_pwm_stopped_check(&config->pwm)) {
}
Expand All @@ -377,15 +386,17 @@

memset(dev->data, 0, sizeof(struct pwm_nrfx_data));
(void)pinctrl_apply_state(config->pcfg, PINCTRL_STATE_SLEEP);

return 0;
}

static int pwm_nrfx_pm_action(const struct device *dev,
enum pm_device_action action)
{
if (action == PM_DEVICE_ACTION_RESUME) {
pwm_resume(dev);
return pwm_resume(dev);
} else if (IS_ENABLED(CONFIG_PM_DEVICE) && (action == PM_DEVICE_ACTION_SUSPEND)) {
pwm_suspend(dev);
return pwm_suspend(dev);
} else {
return -ENOTSUP;
}
Expand Down Expand Up @@ -425,6 +436,11 @@
COND_CODE_1(PWM_HAS_PROP(idx, memory_regions), \
(DT_PROP_OR(PWM_MEM_REGION(idx), zephyr_memory_attr, 0)), (0))

#define PWM_INIT_PRIORITY(idx) \
COND_CODE_1(PWM_NRFX_IS_FAST(_, /*empty*/, idx, _), \
(UTIL_INC(CONFIG_CLOCK_CONTROL_NRF2_GLOBAL_HSFLL_INIT_PRIORITY)), \
(CONFIG_PWM_INIT_PRIORITY))

#define PWM_NRFX_DEVICE(idx) \
NRF_DT_CHECK_NODE_HAS_PINCTRL_SLEEP(PWM(idx)); \
static struct pwm_nrfx_data pwm_nrfx_##idx##_data; \
Expand Down Expand Up @@ -452,14 +468,13 @@
(16ul * 1000ul * 1000ul)), \
IF_ENABLED(CONFIG_DCACHE, \
(.mem_attr = PWM_GET_MEM_ATTR(idx),)) \
IF_ENABLED(PWM_NRFX_USE_CLOCK_CONTROL, \
(.clk_dev = DEVICE_DT_GET(DT_CLOCKS_CTLR(PWM(idx))), \
IF_ENABLED(PWM_NRFX_USE_CLOCK_CONTROL, \
(.clk_dev = PWM_NRFX_IS_FAST(_, /*empty*/, idx, _) \
? DEVICE_DT_GET(DT_CLOCKS_CTLR(PWM(idx))) \
: NULL, \
.clk_spec = { \
.frequency = \
NRF_PERIPH_GET_FREQUENCY(PWM(idx)), \
.accuracy = 0, \
.precision = \
NRF_CLOCK_CONTROL_PRECISION_DEFAULT, \
},)) \
}; \
static int pwm_nrfx_init##idx(const struct device *dev) \
Expand All @@ -473,9 +488,9 @@
pwm_nrfx_init##idx, PM_DEVICE_DT_GET(PWM(idx)), \
&pwm_nrfx_##idx##_data, \
&pwm_nrfx_##idx##_config, \
POST_KERNEL, PWM_NRFX_INIT_PRIORITY, \
POST_KERNEL, PWM_INIT_PRIORITY(idx), \
&pwm_nrfx_drv_api_funcs)

Check notice on line 493 in drivers/pwm/pwm_nrfx.c

View workflow job for this annotation

GitHub Actions / Run compliance checks on patch series (PR)

You may want to run clang-format on this change

drivers/pwm/pwm_nrfx.c:493 -#define PWM_INIT_PRIORITY(idx) \ - COND_CODE_1(PWM_NRFX_IS_FAST(_, /*empty*/, idx, _), \ - (UTIL_INC(CONFIG_CLOCK_CONTROL_NRF2_GLOBAL_HSFLL_INIT_PRIORITY)), \ +#define PWM_INIT_PRIORITY(idx) \ + COND_CODE_1(PWM_NRFX_IS_FAST(_, /*empty*/, idx, _), \ + (UTIL_INC(CONFIG_CLOCK_CONTROL_NRF2_GLOBAL_HSFLL_INIT_PRIORITY)), \ (CONFIG_PWM_INIT_PRIORITY)) -#define PWM_NRFX_DEVICE(idx) \ - NRF_DT_CHECK_NODE_HAS_PINCTRL_SLEEP(PWM(idx)); \ - static struct pwm_nrfx_data pwm_nrfx_##idx##_data; \ - static uint16_t pwm_##idx##_seq_values[NRF_PWM_CHANNEL_COUNT] \ - PWM_MEMORY_SECTION(idx); \ - PINCTRL_DT_DEFINE(PWM(idx)); \ - static const struct pwm_nrfx_config pwm_nrfx_##idx##_config = { \ - .pwm = NRFX_PWM_INSTANCE(idx), \ - .initial_config = { \ - .skip_gpio_cfg = true, \ - .skip_psel_cfg = true, \ - .base_clock = NRF_PWM_CLK_1MHz, \ - .count_mode = (PWM_PROP(idx, center_aligned) \ - ? NRF_PWM_MODE_UP_AND_DOWN \ - : NRF_PWM_MODE_UP), \ - .top_value = 1000, \ - .load_mode = NRF_PWM_LOAD_INDIVIDUAL, \ - .step_mode = NRF_PWM_STEP_TRIGGERED, \ - }, \ - .seq.values.p_raw = pwm_##idx##_seq_values, \ - .seq.length = NRF_PWM_CHANNEL_COUNT, \ - .pcfg = PINCTRL_DT_DEV_CONFIG_GET(PWM(idx)), \ - .clock_freq = COND_CODE_1(DT_CLOCKS_HAS_IDX(PWM(idx), 0), \ - (DT_PROP(DT_CLOCKS_CTLR(PWM(idx)), clock_frequency)), \ - (16ul * 1000ul * 1000ul)), \ - IF_ENABLED(CONFIG_DCACHE, \ - (.mem_attr = PWM_GET_MEM_ATTR(idx),)) \ - IF_ENABLED(PWM_NRFX_USE_CLOCK_CONTROL, \ - (.clk_dev = PWM_NRFX_IS_FAST(_, /*empty*/, idx, _) \ - ? DEVICE_DT_GET(DT_CLOCKS_CTLR(PWM(idx))) \ - : NULL, \ - .clk_spec = { \ - .frequency = \ - NRF_PERIPH_GET_FREQUENCY(PWM(idx)), \ - },)) \ - }; \ - static int pwm_nrfx_init##idx(const struct device *dev) \ - { \ - IRQ_CONNECT(DT_IRQN(PWM(idx)), DT_IRQ(PWM(idx), priority), \ - nrfx_isr, nrfx_pwm_##idx##_irq_handler, 0); \ - return pwm_nrfx_init(dev); \ - }; \ - PM_DEVICE_DT_DEFINE(PWM(idx), pwm_nrfx_pm_action); \ - DEVICE_DT_DEFINE(PWM(idx), \ - pwm_nrfx_init##idx, PM_DEVICE_DT_GET(PWM(idx)), \ - &pwm_nrfx_##idx##_data, \ - &pwm_nrfx_##idx##_config, \ - POST_KERNEL, PWM_INIT_PRIORITY(idx), \ - &pwm_nrfx_drv_api_funcs) +#define PWM_NRFX_DEVICE(idx) \ + NRF_DT_CHECK_NODE_HAS_PINCTRL_SLEEP(PWM(idx)); \ + static struct pwm_nrfx_data pwm_nrfx_##idx##_data; \ + static uint16_t pwm_##idx##_seq_values[NRF_PWM_CHANNEL_COUNT] PWM_MEMORY_SECTION(idx); \ + PINCTRL_DT_DEFINE(PWM(idx)); \ + static const struct pwm_nrfx_config pwm_nrfx_##idx##_config = { \ + .pwm = NRFX_PWM_INSTANCE(idx), \ + .initial_config = \ + { \ + .skip_gpio_cfg = true, \ + .skip_psel_cfg = true, \ + .base_clock = NRF_PWM_CLK_1MHz, \ + .count_mode = \ + (PWM_PROP(idx, center_aligned) ? NRF_PWM_MODE_UP_AND_DOWN \ + : NRF_PWM_MODE_UP), \ + .top_value = 1000,
#define COND_PWM_NRFX_DEVICE(unused, prefix, i, _) \
IF_ENABLED(CONFIG_HAS_HW_NRF_PWM##prefix##i, (PWM_NRFX_DEVICE(prefix##i);))

Expand Down
Loading