diff mbox series

[libpwm,3/4] sysfs: Keep polarity for constant waveforms

Message ID 372ed9bf9ac6c45c651fae81f8be6f909a6b7564.1751995302.git.u.kleine-koenig@baylibre.com
State Accepted
Headers show
Series sysfs: Various fixes and an improvement | expand

Commit Message

Uwe Kleine-König July 8, 2025, 5:24 p.m. UTC
Some waveforms have equivalent representations in sysfs with different
polarities. As some PWMs only support a single polarity, minimize polarity
changes.

Signed-off-by: Uwe Kleine-König <u.kleine-koenig@baylibre.com>
---
 sysfs.c | 58 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 57 insertions(+), 1 deletion(-)
diff mbox series

Patch

diff --git a/sysfs.c b/sysfs.c
index 151b035f72d1..9eac066eb8bf 100644
--- a/sysfs.c
+++ b/sysfs.c
@@ -122,6 +122,43 @@  static struct pwm *pwm_chip_sysfs_get_pwm(struct pwm_chip *chip,
 	return pwm;
 }
 
+static ssize_t pwm_chip_sysfs_read_prop(const struct pwm_sysfs *pwm_sysfs,
+					char *propname,
+					char *buf, size_t count)
+{
+	int fd;
+	va_list ap;
+	int ret;
+	size_t cntread = 0;
+
+	fd = openat(pwm_sysfs->dirfd, propname, O_RDONLY | O_CLOEXEC);
+	if (fd < 0)
+		return -1;
+
+	while (cntread < count) {
+		ret = read(fd, buf + cntread, count - cntread);
+		if (ret < 0) {
+			int saved_errno = errno;
+
+			close(fd);
+
+			errno = saved_errno;
+
+			return ret;
+		} else if (ret == 0) {
+			break;
+		}
+
+		cntread += ret;
+	}
+
+	ret = close(fd);
+	if (ret)
+		return ret;
+
+	return cntread;
+}
+
 static int pwm_chip_sysfs_write_prop(const struct pwm_sysfs *pwm_sysfs,
 					 char *propname,
 					 const char *restrict format, ...)
@@ -173,7 +210,26 @@  static int pwm_chip_sysfs_set_waveform(struct pwm *pwm,
 
 	if (!pwm_sysfs->cache_valid ||
 	    (wf->duty_offset_ns >= wf->period_length_ns - wf->duty_length_ns) != pwm_sysfs->inverted_polarity) {
-		if (wf->duty_offset_ns < wf->period_length_ns - wf->duty_length_ns) {
+		if (wf->duty_length_ns == wf->period_length_ns || wf->duty_length_ns == 0) {
+			/*
+			 * Waveforms with constant inactive output have two
+			 * possible representations in sysfs. Either with normal
+			 * polarity and duty_cycle = 0, or with inverted
+			 * polarity and duty_cycle = period. The analogous
+			 * statement is true for constant active waveforms. As
+			 * many PWMs only support a single polarity, and also to
+			 * minimize sysfs access, keep the current polarity in
+			 * this case.
+			 */
+			if (!pwm_sysfs->cache_valid) {
+				char buf[20];
+
+				ret = pwm_chip_sysfs_read_prop(pwm_sysfs, "polarity", buf, sizeof(buf));
+				if (ret < 0)
+					return ret;
+				pwm_sysfs->inverted_polarity = buf[0] == 'i';
+			}
+		} else if (wf->duty_offset_ns < wf->period_length_ns - wf->duty_length_ns) {
 			ret = pwm_chip_sysfs_write_prop(pwm_sysfs, "polarity", "normal\n");
 			if (ret)
 				return ret;