diff --git a/drivers/pwm/core.c b/drivers/pwm/core.c index f877e77d9184..18d9b816f64b 100644 --- a/drivers/pwm/core.c +++ b/drivers/pwm/core.c @@ -282,6 +282,7 @@ int pwmchip_add_with_polarity(struct pwm_chip *chip, pwm->pwm = chip->base + i; pwm->hwpwm = i; pwm->state.polarity = polarity; + pwm->state.output_type = PWM_OUTPUT_FIXED; if (chip->ops->get_state) chip->ops->get_state(chip, pwm, &pwm->state); diff --git a/drivers/pwm/sysfs.c b/drivers/pwm/sysfs.c index 2389b8669846..1f8f9dbf3189 100644 --- a/drivers/pwm/sysfs.c +++ b/drivers/pwm/sysfs.c @@ -215,11 +215,35 @@ static ssize_t capture_show(struct device *child, return sprintf(buf, "%u %u\n", result.period, result.duty_cycle); } +static ssize_t output_type_show(struct device *child, + struct device_attribute *attr, + char *buf) +{ + const struct pwm_device *pwm = child_to_pwm_device(child); + const char *output_type = "unknown"; + struct pwm_state state; + + pwm_get_state(pwm, &state); + switch (state.output_type) { + case PWM_OUTPUT_FIXED: + output_type = "fixed"; + break; + case PWM_OUTPUT_MODULATED: + output_type = "modulated"; + break; + default: + break; + } + + return snprintf(buf, PAGE_SIZE, "%s\n", output_type); +} + static DEVICE_ATTR_RW(period); static DEVICE_ATTR_RW(duty_cycle); static DEVICE_ATTR_RW(enable); static DEVICE_ATTR_RW(polarity); static DEVICE_ATTR_RO(capture); +static DEVICE_ATTR_RO(output_type); static struct attribute *pwm_attrs[] = { &dev_attr_period.attr, @@ -227,6 +251,7 @@ static struct attribute *pwm_attrs[] = { &dev_attr_enable.attr, &dev_attr_polarity.attr, &dev_attr_capture.attr, + &dev_attr_output_type.attr, NULL }; ATTRIBUTE_GROUPS(pwm); diff --git a/include/linux/pwm.h b/include/linux/pwm.h index b2c9c460947d..fac49238730d 100644 --- a/include/linux/pwm.h +++ b/include/linux/pwm.h @@ -48,6 +48,17 @@ enum { PWMF_EXPORTED = 1 << 1, }; +/** + * enum pwm_output_type - output type of the PWM signal + * @PWM_OUTPUT_FIXED: PWM output is fixed until a change request + * @PWM_OUTPUT_MODULATED: PWM output is modulated in hardware + * autonomously with a predefined pattern + */ +enum pwm_output_type { + PWM_OUTPUT_FIXED = 1 << 0, + PWM_OUTPUT_MODULATED = 1 << 1, +}; + /* * struct pwm_state - state of a PWM channel * @period: PWM period (in nanoseconds) @@ -59,6 +70,7 @@ struct pwm_state { unsigned int period; unsigned int duty_cycle; enum pwm_polarity polarity; + enum pwm_output_type output_type; bool enabled; }; @@ -144,6 +156,16 @@ static inline enum pwm_polarity pwm_get_polarity(const struct pwm_device *pwm) return state.polarity; } +static inline enum pwm_output_type pwm_get_output_type( + const struct pwm_device *pwm) +{ + struct pwm_state state; + + pwm_get_state(pwm, &state); + + return state.output_type; +} + static inline void pwm_get_args(const struct pwm_device *pwm, struct pwm_args *args) { @@ -250,6 +272,7 @@ pwm_set_relative_duty_cycle(struct pwm_state *state, unsigned int duty_cycle, * @get_state: get the current PWM state. This function is only * called once per PWM device when the PWM chip is * registered. + * @get_output_type_supported: get the supported output type of this PWM * @owner: helps prevent removal of modules exporting active PWMs * @config: configure duty cycles and period length for this PWM * @set_polarity: configure the polarity of this PWM @@ -265,6 +288,8 @@ struct pwm_ops { const struct pwm_state *state); void (*get_state)(struct pwm_chip *chip, struct pwm_device *pwm, struct pwm_state *state); + int (*get_output_type_supported)(struct pwm_chip *chip, + struct pwm_device *pwm); struct module *owner; /* Only used by legacy drivers */ @@ -319,6 +344,24 @@ void pwm_free(struct pwm_device *pwm); int pwm_apply_state(struct pwm_device *pwm, const struct pwm_state *state); int pwm_adjust_config(struct pwm_device *pwm); +/** + * pwm_get_output_type_supported() - obtain output type of a PWM device. + * @pwm: PWM device + * + * Returns: output type supported by the PWM device + */ +static inline int pwm_get_output_type_supported(struct pwm_device *pwm) +{ + if (!pwm) + return -EINVAL; + + if (pwm->chip->ops->get_output_type_supported) + return pwm->chip->ops->get_output_type_supported(pwm->chip, + pwm); + + return PWM_OUTPUT_FIXED; +} + /** * pwm_config() - change a PWM device configuration * @pwm: PWM device @@ -437,6 +480,11 @@ static inline int pwm_adjust_config(struct pwm_device *pwm) return -ENOTSUPP; } +static inline int pwm_get_output_type_supported(struct pwm_device *pwm) +{ + return -EINVAL; +} + static inline int pwm_config(struct pwm_device *pwm, int duty_ns, int period_ns) {