| From 5b119f0f1dc8f5b0fd7e143bb12d73776d716c43 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> |
| --- |
| drivers/pwm/core.c | 1 + |
| drivers/pwm/sysfs.c | 25 +++++++++++++++++++++++ |
| include/linux/pwm.h | 49 +++++++++++++++++++++++++++++++++++++++++++++ |
| 3 files changed, 75 insertions(+) |
| |
| diff --git a/drivers/pwm/core.c b/drivers/pwm/core.c |
| index 29078486534d40323015ca255c2b5d5328854b4f..181738005d9632e2db61277d431c84f0bf88819f 100644 |
| --- a/drivers/pwm/core.c |
| +++ b/drivers/pwm/core.c |
| @@ -267,6 +267,7 @@ int __pwmchip_add(struct pwm_chip *chip, struct module *owner) |
| pwm->chip = chip; |
| pwm->pwm = chip->base + i; |
| pwm->hwpwm = i; |
| + pwm->state.output_type = PWM_OUTPUT_FIXED; |
| } |
| |
| list_add(&chip->list, &pwm_chips); |
| diff --git a/drivers/pwm/sysfs.c b/drivers/pwm/sysfs.c |
| index 8d1254761e4dd2ab465008875573c71a7ecfa3e7..1ef6899f2dc88b87271b3197e18b4ebff2bb2458 100644 |
| --- a/drivers/pwm/sysfs.c |
| +++ b/drivers/pwm/sysfs.c |
| @@ -215,11 +215,35 @@ static ssize_t capture_show(struct device *child, |
| 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 = 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 cda3597b84f2c32fbe567c04b3c4114311bed02a..a6b6247e0742283ee59a61e71981f3ce33024e89 100644 |
| --- a/include/linux/pwm.h |
| +++ b/include/linux/pwm.h |
| @@ -45,6 +45,17 @@ 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) |
| @@ -60,6 +71,7 @@ struct pwm_state { |
| u64 period; |
| u64 duty_cycle; |
| enum pwm_polarity polarity; |
| + enum pwm_output_type output_type; |
| bool enabled; |
| bool usage_power; |
| }; |
| @@ -151,6 +163,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) |
| { |
| @@ -265,6 +287,7 @@ struct pwm_capture { |
| * @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 |
| */ |
| struct pwm_ops { |
| int (*request)(struct pwm_chip *chip, struct pwm_device *pwm); |
| @@ -275,6 +298,9 @@ 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); |
| + struct module *owner; |
| }; |
| |
| /** |
| @@ -310,6 +336,24 @@ struct pwm_chip { |
| 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 |
| @@ -418,6 +462,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) |
| { |
| -- |
| 2.43.0.rc2.451.g8631bc7472-goog |
| |