drivers: pwm: rpi_pico: Configuring the divide ratio adaptively
If the `divider-int-0` or variations of these for each channel properties are not specified, or if these is 0, the driver dynamically configures the division ratio by specified cycles. The driver will operate at the specified division ratio if a non-zero value is specified for `divider-int-0`. This is unchanged from previous behavior. Please specify ``divider-int-0`` explicitly to make the same behavior as before. In addition, the default device tree properties related to the division ratio have been removed. Signed-off-by: TOKITA Hiroshi <tokita.hiroshi@gmail.com>
This commit is contained in:
parent
5c9c95b593
commit
275162fd52
|
@ -152,7 +152,6 @@ zephyr_udc0: &usbd {
|
|||
&pwm {
|
||||
pinctrl-0 = <&pwm_ch4b_default>;
|
||||
pinctrl-names = "default";
|
||||
divider-int-0 = <255>;
|
||||
};
|
||||
|
||||
&vreg {
|
||||
|
|
|
@ -213,6 +213,19 @@ Interrupt Controller
|
|||
LED Strip
|
||||
=========
|
||||
|
||||
PWM
|
||||
===
|
||||
|
||||
* The Raspberry Pi Pico PWM driver now configures frequency adaptively.
|
||||
This has resulted in a change in how device tree parameters are handled.
|
||||
If the :dtcompatible:`raspberry,pico-pwm`'s ``divider-int-0`` or variations
|
||||
for each channel are specified, or if these are set to 0,
|
||||
the driver dynamically configures the division ratio by specified cycles.
|
||||
The driver will operate at the specified division ratio if a non-zero value is
|
||||
specified for ``divider-int-0``.
|
||||
This is unchanged from previous behavior.
|
||||
Please specify ``divider-int-0`` explicitly to make the same behavior as before.
|
||||
|
||||
SDHC
|
||||
====
|
||||
|
||||
|
|
|
@ -234,6 +234,8 @@ Drivers and Sensors
|
|||
|
||||
* PWM
|
||||
|
||||
* rpi_pico: The driver now configures the divide ratio adaptively.
|
||||
|
||||
* Regulators
|
||||
|
||||
* Reset
|
||||
|
|
|
@ -73,10 +73,15 @@ static int pwm_rpi_get_cycles_per_sec(const struct device *dev, uint32_t ch, uin
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* No need to check for divide by 0 since the minimum value of
|
||||
* pwm_rpi_get_clkdiv is 1
|
||||
*/
|
||||
*cycles = (uint64_t)((float)pclk / pwm_rpi_get_clkdiv(dev, slice));
|
||||
if (cfg->slice_configs[slice].integral == 0) {
|
||||
*cycles = pclk;
|
||||
} else {
|
||||
/* No need to check for divide by 0 since the minimum value of
|
||||
* pwm_rpi_get_clkdiv is 1
|
||||
*/
|
||||
*cycles = (uint64_t)((float)pclk / pwm_rpi_get_clkdiv(dev, slice));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -104,24 +109,46 @@ static void pwm_rpi_set_channel_polarity(const struct device *dev, int slice,
|
|||
static int pwm_rpi_set_cycles(const struct device *dev, uint32_t ch, uint32_t period_cycles,
|
||||
uint32_t pulse_cycles, pwm_flags_t flags)
|
||||
{
|
||||
const struct pwm_rpi_config *cfg = dev->config;
|
||||
int slice = pwm_rpi_channel_to_slice(ch);
|
||||
|
||||
/* this is the channel within a pwm slice */
|
||||
int pico_channel = pwm_rpi_channel_to_pico_channel(ch);
|
||||
int div_int;
|
||||
int div_frac;
|
||||
|
||||
if (ch >= PWM_RPI_NUM_CHANNELS) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
div_int = cfg->slice_configs[slice].integral;
|
||||
div_frac = cfg->slice_configs[slice].frac;
|
||||
|
||||
if (div_int == 0) {
|
||||
div_int = 1;
|
||||
div_frac = 0;
|
||||
while ((period_cycles / div_int - 1) > PWM_RPI_PICO_COUNTER_TOP_MAX) {
|
||||
div_int *= 2;
|
||||
}
|
||||
|
||||
if (div_int > (UINT8_MAX + 1)) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
period_cycles /= div_int;
|
||||
pulse_cycles /= div_int;
|
||||
}
|
||||
|
||||
if (period_cycles - 1 > PWM_RPI_PICO_COUNTER_TOP_MAX ||
|
||||
pulse_cycles > PWM_RPI_PICO_COUNTER_TOP_MAX) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
int slice = pwm_rpi_channel_to_slice(ch);
|
||||
|
||||
/* this is the channel within a pwm slice */
|
||||
int pico_channel = pwm_rpi_channel_to_pico_channel(ch);
|
||||
|
||||
pwm_rpi_set_channel_polarity(dev, slice, pico_channel,
|
||||
(flags & PWM_POLARITY_MASK) == PWM_POLARITY_INVERTED);
|
||||
pwm_set_wrap(slice, period_cycles - 1);
|
||||
pwm_set_chan_level(slice, pico_channel, pulse_cycles);
|
||||
pwm_set_clkdiv_int_frac(slice, div_int, div_frac);
|
||||
|
||||
return 0;
|
||||
};
|
||||
|
@ -160,9 +187,13 @@ static int pwm_rpi_init(const struct device *dev)
|
|||
|
||||
pwm_init(slice_idx, &slice_cfg, false);
|
||||
|
||||
pwm_set_clkdiv_int_frac(slice_idx,
|
||||
cfg->slice_configs[slice_idx].integral,
|
||||
cfg->slice_configs[slice_idx].frac);
|
||||
if (cfg->slice_configs[slice_idx].integral == 0) {
|
||||
pwm_set_clkdiv_int_frac(slice_idx, 1, 0);
|
||||
} else {
|
||||
pwm_set_clkdiv_int_frac(slice_idx,
|
||||
cfg->slice_configs[slice_idx].integral,
|
||||
cfg->slice_configs[slice_idx].frac);
|
||||
}
|
||||
pwm_set_enabled(slice_idx, true);
|
||||
}
|
||||
|
||||
|
@ -171,8 +202,8 @@ static int pwm_rpi_init(const struct device *dev)
|
|||
|
||||
#define PWM_INST_RPI_SLICE_DIVIDER(idx, n) \
|
||||
{ \
|
||||
.integral = DT_INST_PROP(idx, UTIL_CAT(divider_int_, n)), \
|
||||
.frac = DT_INST_PROP(idx, UTIL_CAT(divider_frac_, n)), \
|
||||
.integral = DT_INST_PROP_OR(idx, UTIL_CAT(divider_int_, n), 0), \
|
||||
.frac = DT_INST_PROP_OR(idx, UTIL_CAT(divider_frac_, n), 0), \
|
||||
}
|
||||
|
||||
#define PWM_RPI_INIT(idx) \
|
||||
|
|
|
@ -16,88 +16,75 @@ properties:
|
|||
|
||||
divider-int-0:
|
||||
type: int
|
||||
default: 1
|
||||
description: |
|
||||
The integral part of the divider for pwm slice 0.
|
||||
This number should be in the range 1 - 255. Defaults
|
||||
to 1, the same as the RESET value.
|
||||
If a value between 1 and 255 is set, it will be set to the register
|
||||
as the integer part of the divider.
|
||||
If the value is set to 0 or this property is not defined when setting
|
||||
the number of cycles to PWM, a division ratio appropriate to that value is set.
|
||||
|
||||
divider-frac-0:
|
||||
type: int
|
||||
default: 0
|
||||
description: |
|
||||
The fractional part of the divider for pwm slice 0.
|
||||
This number should be in the range 0 - 15. Defaults
|
||||
to 0, the same as the RESET value.
|
||||
This number should be in the range 0 - 15.
|
||||
When the "divider-int-0" is set to 0 or is not defined, this property will be
|
||||
ignored.
|
||||
|
||||
divider-int-1:
|
||||
type: int
|
||||
default: 1
|
||||
description: See divider-int-0 for help
|
||||
|
||||
divider-frac-1:
|
||||
type: int
|
||||
default: 0
|
||||
description: See divider-frac-0 for help
|
||||
|
||||
divider-int-2:
|
||||
type: int
|
||||
default: 1
|
||||
description: See divider-int-0 for help
|
||||
|
||||
divider-frac-2:
|
||||
type: int
|
||||
default: 0
|
||||
description: See divider-frac-0 for help
|
||||
|
||||
divider-int-3:
|
||||
type: int
|
||||
default: 1
|
||||
description: See divider-int-0 for help
|
||||
|
||||
divider-frac-3:
|
||||
type: int
|
||||
default: 0
|
||||
description: See divider-frac-0 for help
|
||||
|
||||
divider-int-4:
|
||||
type: int
|
||||
default: 1
|
||||
description: See divider-int-0 for help
|
||||
|
||||
divider-frac-4:
|
||||
type: int
|
||||
default: 0
|
||||
description: See divider-frac-0 for help
|
||||
|
||||
divider-int-5:
|
||||
type: int
|
||||
default: 1
|
||||
description: See divider-int-0 for help
|
||||
|
||||
divider-frac-5:
|
||||
type: int
|
||||
default: 0
|
||||
description: See divider-frac-0 for help
|
||||
|
||||
divider-int-6:
|
||||
type: int
|
||||
default: 1
|
||||
description: See divider-int-0 for help
|
||||
|
||||
divider-frac-6:
|
||||
type: int
|
||||
default: 0
|
||||
description: See divider-frac-0 for help
|
||||
|
||||
divider-int-7:
|
||||
type: int
|
||||
default: 1
|
||||
description: See divider-int-0 for help
|
||||
|
||||
divider-frac-7:
|
||||
type: int
|
||||
default: 0
|
||||
description: See divider-frac-0 for help
|
||||
|
||||
"#pwm-cells":
|
||||
|
|
Loading…
Reference in New Issue