blob: 2df4f3c8c4453682e1422d0ee82b7284b5dc1267 [file] [log] [blame]
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