drivers: pwm: pwm_nrfx: place data buffer in specified memory region
Some devices (like nRF54H20) must have PWM data buffer stored in appropriate location. Signed-off-by: Nikodem Kastelik <nikodem.kastelik@nordicsemi.no>
This commit is contained in:
parent
a6f57fae0b
commit
e0b98dccd1
|
@ -10,6 +10,7 @@
|
||||||
#include <soc.h>
|
#include <soc.h>
|
||||||
#include <hal/nrf_gpio.h>
|
#include <hal/nrf_gpio.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
#include <zephyr/linker/devicetree_regions.h>
|
||||||
|
|
||||||
#include <zephyr/logging/log.h>
|
#include <zephyr/logging/log.h>
|
||||||
|
|
||||||
|
@ -45,7 +46,6 @@ struct pwm_nrfx_config {
|
||||||
|
|
||||||
struct pwm_nrfx_data {
|
struct pwm_nrfx_data {
|
||||||
uint32_t period_cycles;
|
uint32_t period_cycles;
|
||||||
uint16_t seq_values[NRF_PWM_CHANNEL_COUNT];
|
|
||||||
/* Bit mask indicating channels that need the PWM generation. */
|
/* Bit mask indicating channels that need the PWM generation. */
|
||||||
uint8_t pwm_needed;
|
uint8_t pwm_needed;
|
||||||
uint8_t prescaler;
|
uint8_t prescaler;
|
||||||
|
@ -56,6 +56,12 @@ struct pwm_nrfx_data {
|
||||||
#error "Current implementation supports maximum 8 channels."
|
#error "Current implementation supports maximum 8 channels."
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
static uint16_t *seq_values_ptr_get(const struct device *dev)
|
||||||
|
{
|
||||||
|
const struct pwm_nrfx_config *config = dev->config;
|
||||||
|
|
||||||
|
return (uint16_t *)config->seq.values.p_raw;
|
||||||
|
}
|
||||||
|
|
||||||
static bool pwm_period_check_and_set(const struct device *dev,
|
static bool pwm_period_check_and_set(const struct device *dev,
|
||||||
uint32_t channel, uint32_t period_cycles)
|
uint32_t channel, uint32_t period_cycles)
|
||||||
|
@ -164,7 +170,7 @@ static int pwm_nrfx_set_cycles(const struct device *dev, uint32_t channel,
|
||||||
needs_pwm = true;
|
needs_pwm = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
data->seq_values[channel] = PWM_NRFX_CH_VALUE(compare_value, inverted);
|
seq_values_ptr_get(dev)[channel] = PWM_NRFX_CH_VALUE(compare_value, inverted);
|
||||||
|
|
||||||
LOG_DBG("channel %u, pulse %u, period %u, prescaler: %u.",
|
LOG_DBG("channel %u, pulse %u, period %u, prescaler: %u.",
|
||||||
channel, pulse_cycles, period_cycles, data->prescaler);
|
channel, pulse_cycles, period_cycles, data->prescaler);
|
||||||
|
@ -249,7 +255,6 @@ static const struct pwm_driver_api pwm_nrfx_drv_api_funcs = {
|
||||||
static int pwm_nrfx_init(const struct device *dev)
|
static int pwm_nrfx_init(const struct device *dev)
|
||||||
{
|
{
|
||||||
const struct pwm_nrfx_config *config = dev->config;
|
const struct pwm_nrfx_config *config = dev->config;
|
||||||
struct pwm_nrfx_data *data = dev->data;
|
|
||||||
uint8_t initially_inverted = 0;
|
uint8_t initially_inverted = 0;
|
||||||
|
|
||||||
int ret = pinctrl_apply_state(config->pcfg, PINCTRL_STATE_DEFAULT);
|
int ret = pinctrl_apply_state(config->pcfg, PINCTRL_STATE_DEFAULT);
|
||||||
|
@ -260,7 +265,7 @@ static int pwm_nrfx_init(const struct device *dev)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (size_t i = 0; i < ARRAY_SIZE(data->seq_values); i++) {
|
for (size_t i = 0; i < NRF_PWM_CHANNEL_COUNT; i++) {
|
||||||
uint32_t psel;
|
uint32_t psel;
|
||||||
|
|
||||||
if (channel_psel_get(i, &psel, config)) {
|
if (channel_psel_get(i, &psel, config)) {
|
||||||
|
@ -273,10 +278,10 @@ static int pwm_nrfx_init(const struct device *dev)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (size_t i = 0; i < ARRAY_SIZE(data->seq_values); i++) {
|
for (size_t i = 0; i < NRF_PWM_CHANNEL_COUNT; i++) {
|
||||||
bool inverted = initially_inverted & BIT(i);
|
bool inverted = initially_inverted & BIT(i);
|
||||||
|
|
||||||
data->seq_values[i] = PWM_NRFX_CH_VALUE(0, inverted);
|
seq_values_ptr_get(dev)[i] = PWM_NRFX_CH_VALUE(0, inverted);
|
||||||
}
|
}
|
||||||
|
|
||||||
nrfx_err_t result = nrfx_pwm_init(&config->pwm,
|
nrfx_err_t result = nrfx_pwm_init(&config->pwm,
|
||||||
|
@ -339,10 +344,19 @@ static int pwm_nrfx_pm_action(const struct device *dev,
|
||||||
|
|
||||||
#define PWM(dev_idx) DT_NODELABEL(pwm##dev_idx)
|
#define PWM(dev_idx) DT_NODELABEL(pwm##dev_idx)
|
||||||
#define PWM_PROP(dev_idx, prop) DT_PROP(PWM(dev_idx), prop)
|
#define PWM_PROP(dev_idx, prop) DT_PROP(PWM(dev_idx), prop)
|
||||||
|
#define PWM_HAS_PROP(idx, prop) DT_NODE_HAS_PROP(PWM(idx), prop)
|
||||||
|
|
||||||
|
#define PWM_MEMORY_SECTION(idx) \
|
||||||
|
COND_CODE_1(PWM_HAS_PROP(idx, memory_regions), \
|
||||||
|
(__attribute__((__section__(LINKER_DT_NODE_REGION_NAME( \
|
||||||
|
DT_PHANDLE(PWM(idx), memory_regions)))))), \
|
||||||
|
())
|
||||||
|
|
||||||
#define PWM_NRFX_DEVICE(idx) \
|
#define PWM_NRFX_DEVICE(idx) \
|
||||||
NRF_DT_CHECK_NODE_HAS_PINCTRL_SLEEP(PWM(idx)); \
|
NRF_DT_CHECK_NODE_HAS_PINCTRL_SLEEP(PWM(idx)); \
|
||||||
static struct pwm_nrfx_data pwm_nrfx_##idx##_data; \
|
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)); \
|
PINCTRL_DT_DEFINE(PWM(idx)); \
|
||||||
static const struct pwm_nrfx_config pwm_nrfx_##idx##_config = { \
|
static const struct pwm_nrfx_config pwm_nrfx_##idx##_config = { \
|
||||||
.pwm = NRFX_PWM_INSTANCE(idx), \
|
.pwm = NRFX_PWM_INSTANCE(idx), \
|
||||||
|
@ -357,7 +371,7 @@ static int pwm_nrfx_pm_action(const struct device *dev,
|
||||||
.load_mode = NRF_PWM_LOAD_INDIVIDUAL, \
|
.load_mode = NRF_PWM_LOAD_INDIVIDUAL, \
|
||||||
.step_mode = NRF_PWM_STEP_TRIGGERED, \
|
.step_mode = NRF_PWM_STEP_TRIGGERED, \
|
||||||
}, \
|
}, \
|
||||||
.seq.values.p_raw = pwm_nrfx_##idx##_data.seq_values, \
|
.seq.values.p_raw = pwm_##idx##_seq_values, \
|
||||||
.seq.length = NRF_PWM_CHANNEL_COUNT, \
|
.seq.length = NRF_PWM_CHANNEL_COUNT, \
|
||||||
.pcfg = PINCTRL_DT_DEV_CONFIG_GET(PWM(idx)), \
|
.pcfg = PINCTRL_DT_DEV_CONFIG_GET(PWM(idx)), \
|
||||||
}; \
|
}; \
|
||||||
|
|
Loading…
Reference in a new issue