diff options
-rw-r--r-- | drivers/pwm/pwm_qmsi.c | 81 | ||||
-rw-r--r-- | include/pwm.h | 12 |
2 files changed, 69 insertions, 24 deletions
diff --git a/drivers/pwm/pwm_qmsi.c b/drivers/pwm/pwm_qmsi.c index 09b443065..070d81837 100644 --- a/drivers/pwm/pwm_qmsi.c +++ b/drivers/pwm/pwm_qmsi.c @@ -158,32 +158,35 @@ pwm_set_port_return: } /* - * Set the duration for on/off timer of PWM. + * Set the time to assert and de-assert the PWM pin. * - * This sets the duration for the pin to low or high. + * This sets the duration for the pin to stay low or high. * - * Assumes a nominal system clock of 32MHz, each count of on/off represents - * 31.25ns (e.g. on == 2 means the pin stays high for 62.5ns). - * The duration of 1 count depends on system clock. Refer to the hardware - * manual for more information. + * For example, with a nominal system clock of 32MHz, each count of on/off + * represents 31.25ns (e.g. off == 2 means the pin is to be de-asserted at + * 62.5ns from the beginning of a PWM cycle). The duration of 1 count depends + * on system clock. Refer to the hardware manual for more information. * * Parameters - * dev: Device struct + * dev: Pointer to PWM device structure * access_op: whether to set one pin or all - * pwm: Which PWM port to set - * on: Duration for pin to stay high (must be >= 2) - * off: Duration for pin to stay low (must be >= 2) + * pwm: PWM port number to set + * on: How far (in timer count) from the beginning of a PWM cycle the PWM + * pin should be asserted. Must be zero, since PWM from Quark MCU always + * starts from high. + * off: How far (in timer count) from the beginning of a PWM cycle the PWM + * pin should be de-asserted. * - * return 0, -ENOTSUP + * return 0, or negative errno code */ static int pwm_qmsi_set_values(struct device *dev, int access_op, - uint32_t pwm, uint32_t on, uint32_t off) + uint32_t pwm, uint32_t on, uint32_t off) { - int i; + uint32_t *channel_period = dev->config->config_info; + int i, high, low; - if (off == 0) { - on--; - off = 1; + if (on) { + return -EINVAL; } switch (access_op) { @@ -192,13 +195,40 @@ static int pwm_qmsi_set_values(struct device *dev, int access_op, if (pwm >= CONFIG_PWM_QMSI_NUM_PORTS) { return -EIO; } - return __set_one_port(dev, QM_PWM_0, pwm, on, off); + + high = off; + low = channel_period[pwm] - off; + + if (off >= channel_period[pwm]) { + high = channel_period[pwm] - 1; + low = 1; + } + + if (off == 0) { + high = 1; + low = channel_period[pwm] - 1; + } + + return __set_one_port(dev, QM_PWM_0, pwm, high, low); case PWM_ACCESS_ALL: for (i = 0; i < CONFIG_PWM_QMSI_NUM_PORTS; i++) { - __set_one_port(dev, QM_PWM_0, i, on, off); + high = off; + low = channel_period[i] - off; + + if (off >= channel_period[i]) { + high = channel_period[i] - 1; + low = 1; + } + + if (off == 0) { + high = 1; + low = channel_period[i] - 1; + } + + return __set_one_port(dev, QM_PWM_0, i, high, low); } - break; + break; default: return -ENOTSUP; } @@ -208,7 +238,7 @@ static int pwm_qmsi_set_values(struct device *dev, int access_op, } static int pwm_qmsi_set_period(struct device *dev, int access_op, - uint32_t pwm, uint32_t period) + uint32_t pwm, uint32_t period) { uint32_t *channel_period = dev->config->config_info; int ret_val = 0; @@ -295,12 +325,23 @@ static int pwm_qmsi_set_duty_cycle(struct device *dev, int access_op, return 0; } +static int pwm_qmsi_set_phase(struct device *dev, int access_op, + uint32_t pwm, uint8_t phase) +{ + ARG_UNUSED(dev); + ARG_UNUSED(access_op); + ARG_UNUSED(pwm); + ARG_UNUSED(phase); + + return -ENOTSUP; +} static struct pwm_driver_api pwm_qmsi_drv_api_funcs = { .config = pwm_qmsi_configure, .set_values = pwm_qmsi_set_values, .set_period = pwm_qmsi_set_period, .set_duty_cycle = pwm_qmsi_set_duty_cycle, + .set_phase = pwm_qmsi_set_phase }; static int pwm_qmsi_init(struct device *dev) diff --git a/include/pwm.h b/include/pwm.h index 85025a1a1..a77686cbd 100644 --- a/include/pwm.h +++ b/include/pwm.h @@ -114,8 +114,10 @@ static inline int pwm_pin_configure(struct device *dev, uint8_t pwm, * * @param dev Pointer to the device structure for the driver instance. * @param pwm PWM output. - * @param on ON value set to the PWM. - * @param off OFF value set to the PWM. + * @param on ON value (number of timer count) set to the PWM. HW specific. + * How far from the beginning of a PWM cycle the PWM pulse starts. + * @param off OFF value (number of timer count) set to the PWM. HW specific. + * How far from the beginning of a PWM cycle the PWM pulse stops. * * @retval 0 If successful. * @retval Negative errno code if failure. @@ -220,8 +222,10 @@ static inline int pwm_all_configure(struct device *dev, int flags) * @brief Set the ON/OFF values for all PWM outputs. * * @param dev Pointer to the device structure for the driver instance. - * @param on ON value set to the PWM. - * @param off OFF value set to the PWM. + * @param on ON value (number of timer count) set to the PWM. HW specific. + * How far from the beginning of a PWM cycle the PWM pulse starts. + * @param off OFF value (number of timer count) set to the PWM. HW specific. + * How far from the beginning of a PWM cycle the PWM pulse stops. * * @retval 0 If successful. * @retval Negative errno code if failure. |