lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Date:	Tue, 23 Sep 2014 16:17:26 -0700
From:	Doug Anderson <dianders@...omium.org>
To:	thierry.reding@...il.com, Linus Walleij <linus.walleij@...aro.org>,
	Mark Brown <broonie@...nel.org>,
	Lee Jones <lee.jones@...aro.org>
Cc:	Chris Zhong <zyw@...k-chips.com>, Heiko Stuebner <heiko@...ech.de>,
	Sonny Rao <sonnyrao@...omium.org>,
	Doug Anderson <dianders@...omium.org>,
	linux-pwm@...r.kernel.org, linux-kernel@...r.kernel.org
Subject: [RFC PATCH] pwm: Add the concept of an "active" pinctrl

There are cases where you really don't want a PWM's pinctrl to take
effect until you know that the PWM is driving at the proper rate.  A
good example of this is a PWM-controlled regulator, where the boot
state of the pin (maybe a pulled down input) could cause a vastly
different voltage to take effect than having the pin setup as a PWM
but not having the PWM enabled yet.

Let's add a feature where you can define an "active" pinctrl state.
This state (if it exists) will be applied after the PWM has actually
been enabled.  If the PWM is ever disabled we'll go back to "default"
state.

Signed-off-by: Doug Anderson <dianders@...omium.org>
---
I'm sure Linus W or Thierry or Mark will tell me this is an idiotic
idea (or totally the wrong way to do it), but I figured I'd float it
out there and maybe someone can tell me something better to do.  ;)

 drivers/pwm/core.c  | 34 +++++++++++++++++++++++++++++++---
 include/linux/pwm.h |  8 ++++++++
 2 files changed, 39 insertions(+), 3 deletions(-)

diff --git a/drivers/pwm/core.c b/drivers/pwm/core.c
index 966497d..12f86e0 100644
--- a/drivers/pwm/core.c
+++ b/drivers/pwm/core.c
@@ -245,6 +245,14 @@ int pwmchip_add(struct pwm_chip *chip)
 	if (ret < 0)
 		goto out;
 
+	chip->pinctrl = devm_pinctrl_get(chip->dev);
+	if (!IS_ERR_OR_NULL(chip->pinctrl)) {
+		chip->state_default = pinctrl_lookup_state(chip->pinctrl,
+							   "default");
+		chip->state_active = pinctrl_lookup_state(chip->pinctrl,
+							  "active");
+	}
+
 	chip->pwms = kzalloc(chip->npwm * sizeof(*pwm), GFP_KERNEL);
 	if (!chip->pwms) {
 		ret = -ENOMEM;
@@ -457,8 +465,17 @@ EXPORT_SYMBOL_GPL(pwm_set_polarity);
  */
 int pwm_enable(struct pwm_device *pwm)
 {
-	if (pwm && !test_and_set_bit(PWMF_ENABLED, &pwm->flags))
-		return pwm->chip->ops->enable(pwm->chip, pwm);
+	int ret;
+
+	if (pwm && !test_and_set_bit(PWMF_ENABLED, &pwm->flags)) {
+		ret = pwm->chip->ops->enable(pwm->chip, pwm);
+
+		if (!ret && !IS_ERR_OR_NULL(pwm->chip->state_active))
+			ret = pinctrl_select_state(pwm->chip->pinctrl,
+						   pwm->chip->state_active);
+
+		return ret;
+	}
 
 	return pwm ? 0 : -EINVAL;
 }
@@ -470,8 +487,19 @@ EXPORT_SYMBOL_GPL(pwm_enable);
  */
 void pwm_disable(struct pwm_device *pwm)
 {
-	if (pwm && test_and_clear_bit(PWMF_ENABLED, &pwm->flags))
+	int ret;
+
+	if (pwm && test_and_clear_bit(PWMF_ENABLED, &pwm->flags)) {
+		if (!IS_ERR_OR_NULL(pwm->chip->state_default)) {
+			ret = pinctrl_select_state(pwm->chip->pinctrl,
+						   pwm->chip->state_default);
+			if (ret)
+				dev_warn(pwm->chip->dev,
+					 "Couldn't set def state: %d\n", ret);
+		}
+
 		pwm->chip->ops->disable(pwm->chip, pwm);
+	}
 }
 EXPORT_SYMBOL_GPL(pwm_disable);
 
diff --git a/include/linux/pwm.h b/include/linux/pwm.h
index e90628c..039c898 100644
--- a/include/linux/pwm.h
+++ b/include/linux/pwm.h
@@ -162,6 +162,10 @@ struct pwm_ops {
  * @pwms: array of PWM devices allocated by the framework
  * @can_sleep: must be true if the .config(), .enable() or .disable()
  *             operations may sleep
+ *
+ * @pinctrl: Pointer to the a pinctrl for the dev
+ * @state_default: We'll apply this when a PWM is disabled
+ * @state_active: We'll apply this when a PWM is enabled
  */
 struct pwm_chip {
 	struct device		*dev;
@@ -176,6 +180,10 @@ struct pwm_chip {
 					    const struct of_phandle_args *args);
 	unsigned int		of_pwm_n_cells;
 	bool			can_sleep;
+
+	struct pinctrl *pinctrl;
+	struct pinctrl_state *state_default;
+	struct pinctrl_state *state_active;
 };
 
 #if IS_ENABLED(CONFIG_PWM)
-- 
2.1.0.rc2.206.gedb03e5

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Powered by blists - more mailing lists