All of lore.kernel.org
 help / color / mirror / Atom feed
From: Alexander Stein <alexander.stein@ew.tq-group.com>
To: "Bartlomiej Zolnierkiewicz" <b.zolnierkie@samsung.com>,
	"Jean Delvare" <jdelvare@suse.com>,
	"Guenter Roeck" <linux@roeck-us.net>,
	"Jonathan Corbet" <corbet@lwn.net>,
	"Thierry Reding" <thierry.reding@gmail.com>,
	"Uwe Kleine-König" <u.kleine-koenig@pengutronix.de>,
	"Lee Jones" <lee.jones@linaro.org>
Cc: Alexander Stein <alexander.stein@ew.tq-group.com>,
	linux-hwmon@vger.kernel.org, linux-pwm@vger.kernel.org,
	Markus Niebel <Markus.Niebel@ew.tq-group.com>
Subject: [PATCH v3 6/6] hwmon: pwm-fan: Add hwmon_pwm_enable attribute
Date: Tue, 17 May 2022 16:26:20 +0200	[thread overview]
Message-ID: <20220517142620.1523143-7-alexander.stein@ew.tq-group.com> (raw)
In-Reply-To: <20220517142620.1523143-1-alexander.stein@ew.tq-group.com>

This adds the enable attribute which is used to differentiate if PWM duty
means to switch off regulator and PWM or to keep them enabled but
at inactive PWM output level.

Signed-off-by: Alexander Stein <alexander.stein@ew.tq-group.com>
---
 Documentation/hwmon/pwm-fan.rst | 10 ++++
 drivers/hwmon/pwm-fan.c         | 95 +++++++++++++++++++++++++++++----
 2 files changed, 95 insertions(+), 10 deletions(-)

diff --git a/Documentation/hwmon/pwm-fan.rst b/Documentation/hwmon/pwm-fan.rst
index 82fe96742fee..0083480068d1 100644
--- a/Documentation/hwmon/pwm-fan.rst
+++ b/Documentation/hwmon/pwm-fan.rst
@@ -18,3 +18,13 @@ the hwmon's sysfs interface.
 
 The fan rotation speed returned via the optional 'fan1_input' is extrapolated
 from the sampled interrupts from the tachometer signal within 1 second.
+
+The driver provides the following sensor accesses in sysfs:
+
+=============== ======= =======================================================
+fan1_input	ro	fan tachometer speed in RPM
+pwm1_enable	rw	keep enable mode, defines behaviour when pwm1=0
+			0=switch off regulator and disable PWM
+			1=keep regulator enabled and set PWM to inactive level
+pwm1		rw	relative speed (0-255), 255=max. speed.
+=============== ======= =======================================================
diff --git a/drivers/hwmon/pwm-fan.c b/drivers/hwmon/pwm-fan.c
index 9ebe958cc908..cb29206ddcdc 100644
--- a/drivers/hwmon/pwm-fan.c
+++ b/drivers/hwmon/pwm-fan.c
@@ -35,6 +35,7 @@ struct pwm_fan_ctx {
 	struct pwm_device *pwm;
 	struct regulator *reg_en;
 	bool enabled;
+	bool keep_enabled;
 
 	int tach_count;
 	struct pwm_fan_tach *tachs;
@@ -129,7 +130,8 @@ static int pwm_fan_power_off(struct pwm_fan_ctx *ctx)
 		return 0;
 
 	pwm_get_state(ctx->pwm, &state);
-	state.enabled = false;
+	if (!ctx->keep_enabled)
+		state.enabled = false;
 	state.duty_cycle = 0;
 	pwm_apply_state(ctx->pwm, &state);
 
@@ -178,20 +180,87 @@ static void pwm_fan_update_state(struct pwm_fan_ctx *ctx, unsigned long pwm)
 	ctx->pwm_fan_state = i;
 }
 
+static int pwm_fan_update_enable(struct pwm_fan_ctx *ctx, long val)
+{
+	struct pwm_state old_state;
+	int ret;
+
+	pwm_get_state(ctx->pwm, &old_state);
+
+	if (val) {
+		/*
+		 * If PWM is already enabled, nothing will change
+		 * If PWM is disabled, it will enable with inactive level (duty == 0)
+		 */
+		ret = pwm_fan_enable_pwm(ctx);
+		if (ret) {
+			dev_err(ctx->dev, "failed to apply PWM state\n");
+			return ret;
+		}
+
+		/* Increase regulator reference counter to prevent switching off */
+		ret = regulator_enable(ctx->reg_en);
+		if (ret < 0) {
+			dev_err(ctx->dev, "failed to enable regulator\n");
+			/* Restore old state */
+			pwm_apply_state(ctx->pwm, &old_state);
+		}
+	} else {
+		/* Only disable PWM if currently on inactive state */
+		if (!ctx->pwm_value) {
+			struct pwm_state disable_state;
+
+			pwm_get_state(ctx->pwm, &disable_state);
+			disable_state.duty_cycle = 0;
+			disable_state.enabled = false;
+			ret = pwm_apply_state(ctx->pwm, &disable_state);
+			if (ret) {
+				dev_err(ctx->dev, "failed to apply PWM state\n");
+				return ret;
+			}
+		}
+		/* Decrease regulator reference counter */
+		ret = regulator_disable(ctx->reg_en);
+		if (ret < 0) {
+			dev_err(ctx->dev, "failed to decrease power supply usage\n");
+			/* Restore old state */
+			pwm_apply_state(ctx->pwm, &old_state);
+		}
+	}
+	if (ret == 0)
+		ctx->keep_enabled = val;
+
+	return ret;
+}
+
 static int pwm_fan_write(struct device *dev, enum hwmon_sensor_types type,
 			 u32 attr, int channel, long val)
 {
 	struct pwm_fan_ctx *ctx = dev_get_drvdata(dev);
 	int ret;
 
-	if (val < 0 || val > MAX_PWM)
-		return -EINVAL;
+	switch (attr) {
+	case hwmon_pwm_input:
+		if (val < 0 || val > MAX_PWM)
+			return -EINVAL;
+		ret = __set_pwm(ctx, val);
+		if (ret)
+			return ret;
+		pwm_fan_update_state(ctx, val);
+		break;
+	case hwmon_pwm_enable:
+		mutex_lock(&ctx->lock);
+		if (val < 0 || val > 1)
+			ret = -EINVAL;
+		else if (ctx->keep_enabled != val)
+			ret = pwm_fan_update_enable(ctx, val);
+		mutex_unlock(&ctx->lock);
 
-	ret = __set_pwm(ctx, val);
-	if (ret)
 		return ret;
+	default:
+		return -EOPNOTSUPP;
+	}
 
-	pwm_fan_update_state(ctx, val);
 	return 0;
 }
 
@@ -202,9 +271,15 @@ static int pwm_fan_read(struct device *dev, enum hwmon_sensor_types type,
 
 	switch (type) {
 	case hwmon_pwm:
-		*val = ctx->pwm_value;
-		return 0;
-
+		switch (attr) {
+		case hwmon_pwm_input:
+			*val = ctx->pwm_value;
+			return 0;
+		case hwmon_pwm_enable:
+			*val = ctx->keep_enabled;
+			return 0;
+		}
+		return -EOPNOTSUPP;
 	case hwmon_fan:
 		*val = ctx->tachs[channel].rpm;
 		return 0;
@@ -436,7 +511,7 @@ static int pwm_fan_probe(struct platform_device *pdev)
 	if (!channels)
 		return -ENOMEM;
 
-	channels[0] = HWMON_CHANNEL_INFO(pwm, HWMON_PWM_INPUT);
+	channels[0] = HWMON_CHANNEL_INFO(pwm, HWMON_PWM_INPUT | HWMON_PWM_ENABLE);
 
 	for (i = 0; i < ctx->tach_count; i++) {
 		struct pwm_fan_tach *tach = &ctx->tachs[i];
-- 
2.25.1


  parent reply	other threads:[~2022-05-17 14:26 UTC|newest]

Thread overview: 16+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-05-17 14:26 [PATCH v3 0/6] hwmon: pwm-fan: switch regulator dynamically Alexander Stein
2022-05-17 14:26 ` [PATCH v3 1/6] hwmon: pwm-fan: Refactor fan power on/off Alexander Stein
2022-05-17 14:26 ` [PATCH v3 2/6] hwmon: pwm-fan: Simplify enable/disable check Alexander Stein
2022-05-17 14:26 ` [PATCH v3 3/6] hwmon: pwm-fan: Dynamically switch off regulator if PWM duty is 0 Alexander Stein
2022-05-17 14:26 ` [PATCH v3 4/6] hwmon: pwm-fan: Remove internal duplicated pwm_state Alexander Stein
2022-05-17 14:26 ` [PATCH v3 5/6] hwmon: pwm-fan: Move PWM enable into separate function Alexander Stein
2022-05-17 14:26 ` Alexander Stein [this message]
2022-05-17 14:53   ` [PATCH v3 6/6] hwmon: pwm-fan: Add hwmon_pwm_enable attribute Uwe Kleine-König
2022-05-17 16:32     ` Guenter Roeck
2022-05-17 16:57       ` Uwe Kleine-König
2022-05-17 17:32         ` Guenter Roeck
2022-05-18  6:55           ` Alexander Stein
2022-05-17 16:38   ` Guenter Roeck
2022-05-17 17:06     ` Uwe Kleine-König
2022-05-18  7:06       ` (EXT) " Alexander Stein
2022-05-18 14:20         ` Guenter Roeck

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20220517142620.1523143-7-alexander.stein@ew.tq-group.com \
    --to=alexander.stein@ew.tq-group.com \
    --cc=Markus.Niebel@ew.tq-group.com \
    --cc=b.zolnierkie@samsung.com \
    --cc=corbet@lwn.net \
    --cc=jdelvare@suse.com \
    --cc=lee.jones@linaro.org \
    --cc=linux-hwmon@vger.kernel.org \
    --cc=linux-pwm@vger.kernel.org \
    --cc=linux@roeck-us.net \
    --cc=thierry.reding@gmail.com \
    --cc=u.kleine-koenig@pengutronix.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.