| From f5b043f0d5576f1a5127e15f7446eef90909e50e Mon Sep 17 00:00:00 2001 |
| From: Fenglin Wu <fenglinw@codeaurora.org> |
| Date: Mon, 4 Dec 2017 09:56:51 +0800 |
| Subject: [PATCH] BACKPORT: FROMLIST: pwm: Add support for different PWM output |
| types |
| |
| Normally, PWM channels have fixed output until software requests to |
| change their settings. There are some PWM devices whose outputs can be |
| changed autonomously according to a predefined pattern programmed in |
| hardware. |
| |
| Add support for such devices by adding a new pwm_output_type enum type |
| to identify these two different PWM types and adding helper functions to |
| read the PWM output type supported by a PWM. |
| |
| Bug: 140290585 |
| Link: https://lore.kernel.org/lkml/1568415464-20267-1-git-send-email-gurus@codeaurora.org/ |
| Change-Id: Ie8d61975057c51258e5bde9451ce96be4acdf98b |
| Signed-off-by: Fenglin Wu <fenglinw@codeaurora.org> |
| [gurus@codeaurora.org: removed output_pattern, changed output_type sysfs |
| param to read-only, reworded commit message] |
| Signed-off-by: Guru Das Srinagesh <gurus@codeaurora.org> |
| Kcr-patch: 0622211c88a55d017f48378c3847736dfe945efa385c3c6feda5a853.patch |
| --- |
| drivers/pwm/core.c | 26 +++++++++++++++++++++++++ |
| include/linux/pwm.h | 47 +++++++++++++++++++++++++++++++++++++++++++++ |
| 2 files changed, 73 insertions(+) |
| |
| diff --git a/drivers/pwm/core.c b/drivers/pwm/core.c |
| index 8acbcf5b66739f13be83026aea37b1d4d573bc89..36ae6186b216255eb5e1f3149758513203814683 100644 |
| --- a/drivers/pwm/core.c |
| +++ b/drivers/pwm/core.c |
| @@ -691,11 +691,35 @@ static ssize_t capture_show(struct device *pwm_dev, |
| return sysfs_emit(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 = pwm_from_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, |
| @@ -703,6 +727,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); |
| @@ -1034,6 +1059,7 @@ struct pwm_chip *pwmchip_alloc(struct device *parent, unsigned int npwm, size_t |
| struct pwm_device *pwm = &chip->pwms[i]; |
| pwm->chip = chip; |
| pwm->hwpwm = i; |
| + pwm->state.output_type = PWM_OUTPUT_FIXED; |
| } |
| |
| return chip; |
| diff --git a/include/linux/pwm.h b/include/linux/pwm.h |
| index f8c2dc12dbd37fd907975142abd900083fe32a9d..fe0d4d06fa640cc3465bc66b1df3f67c686602d1 100644 |
| --- a/include/linux/pwm.h |
| +++ b/include/linux/pwm.h |
| @@ -49,6 +49,16 @@ enum { |
| PWMF_EXPORTED = 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) |
| @@ -64,6 +74,7 @@ struct pwm_state { |
| u64 period; |
| u64 duty_cycle; |
| enum pwm_polarity polarity; |
| + enum pwm_output_type output_type; |
| bool enabled; |
| bool usage_power; |
| }; |
| @@ -141,6 +152,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) |
| { |
| @@ -253,6 +274,7 @@ struct pwm_capture { |
| * @capture: capture and report PWM signal |
| * @apply: atomically apply a new PWM config |
| * @get_state: get the current PWM state. |
| + * @get_output_type_supported: get the supported output type of this PWM |
| */ |
| struct pwm_ops { |
| int (*request)(struct pwm_chip *chip, struct pwm_device *pwm); |
| @@ -263,6 +285,8 @@ struct pwm_ops { |
| const struct pwm_state *state); |
| int (*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); |
| }; |
| |
| /** |
| @@ -314,6 +338,24 @@ int pwm_apply_might_sleep(struct pwm_device *pwm, const struct pwm_state *state) |
| int pwm_apply_atomic(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 |
| @@ -444,6 +486,11 @@ static inline int pwm_adjust_config(struct pwm_device *pwm) |
| return -EOPNOTSUPP; |
| } |
| |
| +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) |
| { |
| -- |
| 2.46.0.rc2.264.g509ed76dc8-goog |
| |