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-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <20240228133236.748225-4-dima.fedrau@gmail.com>
Date: Wed, 28 Feb 2024 14:32:35 +0100
From: Dimitri Fedrau <dima.fedrau@...il.com>
To: 
Cc: Dimitri Fedrau <dima.fedrau@...il.com>,
	Uwe Kleine-König <u.kleine-koenig@...gutronix.de>,
	linux-kernel@...r.kernel.org,
	linux-pwm@...r.kernel.org
Subject: [PATCH 3/3] pwm: mc33xs2410: add support for direct inputs

Add support for direct inputs, which are used to directly turn-on or
turn-off the outputs. Direct inputs have the advantage over the SPI
controlled outputs that they aren't limited to the frequency steps.
Frequency resolution depends on the input signal, range is still
from 0.5Hz to 2.048kHz.

Signed-off-by: Dimitri Fedrau <dima.fedrau@...il.com>
---
 drivers/pwm/pwm-mc33xs2410.c | 116 +++++++++++++++++++++++++++++++----
 1 file changed, 105 insertions(+), 11 deletions(-)

diff --git a/drivers/pwm/pwm-mc33xs2410.c b/drivers/pwm/pwm-mc33xs2410.c
index 35753039da6b..828a67227185 100644
--- a/drivers/pwm/pwm-mc33xs2410.c
+++ b/drivers/pwm/pwm-mc33xs2410.c
@@ -18,7 +18,10 @@
 #define MC33XS2410_GLB_CTRL_MODE_MASK	GENMASK(7, 6)
 #define MC33XS2410_GLB_CTRL_NORMAL_MODE	BIT(6)
 #define MC33XS2410_GLB_CTRL_SAFE_MODE	BIT(7)
+#define MC33XS2410_GLB_CTRL_CMOS_LEVEL	BIT(0)
 #define MC33XS2410_OUT1_4_CTRL		0x02
+#define MC33XS2410_IN_CTRL1		0x03
+#define MC33XS2410_IN_CTRL1_IN_EN(x)	BIT(x)
 #define MC33XS2410_PWM_CTRL1		0x05
 #define MC33XS2410_PWM_CTRL1_POL_INV(x)	BIT(x)
 #define MC33XS2410_PWM_CTRL3		0x07
@@ -45,6 +48,7 @@
 struct mc33xs2410_pwm {
 	struct pwm_chip chip;
 	struct spi_device *spi;
+	struct pwm_device *di[4];
 	struct mutex lock;
 };
 
@@ -154,20 +158,15 @@ static u8 mc33xs2410_pwm_get_freq(const struct pwm_state *state)
 	return (ret | FIELD_PREP(MC33XS2410_PWM_FREQ_STEP_MASK, step));
 }
 
-static int mc33xs2410_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
-				const struct pwm_state *state)
+static int mc33xs2410_pwm_apply_spi(struct pwm_chip *chip,
+				    struct pwm_device *pwm,
+				    const struct pwm_state *state)
 {
 	struct mc33xs2410_pwm *mc33xs2410 = mc33xs2410_pwm_from_chip(chip);
 	struct spi_device *spi = mc33xs2410->spi;
 	u8 mask, val;
 	int ret;
 
-	if (state->period > mc33xs2410_period[STEP_05HZ][MC33XS2410_PERIOD_MAX])
-		return -EINVAL;
-
-	if (state->period < mc33xs2410_period[STEP_32HZ][MC33XS2410_PERIOD_MIN])
-		return -EINVAL;
-
 	guard(mutex)(&mc33xs2410->lock);
 	mask = MC33XS2410_PWM_CTRL1_POL_INV(pwm->hwpwm);
 	val = (state->polarity == PWM_POLARITY_INVERSED) ? mask : 0;
@@ -190,9 +189,38 @@ static int mc33xs2410_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
 	return mc33xs2410_modify_reg(spi, MC33XS2410_PWM_CTRL3, mask, val);
 }
 
-static int mc33xs2410_pwm_get_state(struct pwm_chip *chip,
-				    struct pwm_device *pwm,
-				    struct pwm_state *state)
+static int mc33xs2410_pwm_apply_direct_inputs(struct pwm_chip *chip,
+					      struct pwm_device *pwm,
+					      const struct pwm_state *state)
+{
+	struct mc33xs2410_pwm *mc33xs2410 = mc33xs2410_pwm_from_chip(chip);
+	struct pwm_device *di = mc33xs2410->di[pwm->hwpwm];
+
+	guard(mutex)(&mc33xs2410->lock);
+
+	return pwm_apply_state(di, state);
+}
+
+static int mc33xs2410_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
+				const struct pwm_state *state)
+{
+	struct mc33xs2410_pwm *mc33xs2410 = mc33xs2410_pwm_from_chip(chip);
+
+	if (state->period > mc33xs2410_period[STEP_05HZ][MC33XS2410_PERIOD_MAX])
+		return -EINVAL;
+
+	if (state->period < mc33xs2410_period[STEP_32HZ][MC33XS2410_PERIOD_MIN])
+		return -EINVAL;
+
+	if (mc33xs2410->di[pwm->hwpwm])
+		return mc33xs2410_pwm_apply_direct_inputs(chip, pwm, state);
+	else
+		return mc33xs2410_pwm_apply_spi(chip, pwm, state);
+}
+
+static int mc33xs2410_pwm_get_state_spi(struct pwm_chip *chip,
+					struct pwm_device *pwm,
+					struct pwm_state *state)
 {
 	struct mc33xs2410_pwm *mc33xs2410 = mc33xs2410_pwm_from_chip(chip);
 	struct spi_device *spi = mc33xs2410->spi;
@@ -236,6 +264,28 @@ static int mc33xs2410_pwm_get_state(struct pwm_chip *chip,
 	return 0;
 }
 
+static int mc33xs2410_pwm_get_state_direct_inputs(struct pwm_chip *chip,
+						  struct pwm_device *pwm,
+						  struct pwm_state *state)
+{
+	struct mc33xs2410_pwm *mc33xs2410 = mc33xs2410_pwm_from_chip(chip);
+
+	pwm_get_state(mc33xs2410->di[pwm->hwpwm], state);
+	return 0;
+}
+
+static int mc33xs2410_pwm_get_state(struct pwm_chip *chip,
+				    struct pwm_device *pwm,
+				    struct pwm_state *state)
+{
+	struct mc33xs2410_pwm *mc33xs2410 = mc33xs2410_pwm_from_chip(chip);
+
+	if (mc33xs2410->di[pwm->hwpwm])
+		return mc33xs2410_pwm_get_state_direct_inputs(chip, pwm, state);
+	else
+		return mc33xs2410_pwm_get_state_spi(chip, pwm, state);
+}
+
 static const struct pwm_ops mc33xs2410_pwm_ops = {
 	.apply = mc33xs2410_pwm_apply,
 	.get_state = mc33xs2410_pwm_get_state,
@@ -257,6 +307,45 @@ static int mc33xs2410_reset(struct device *dev)
 	return 0;
 }
 
+static int mc33xs2410_direct_inputs_probe(struct mc33xs2410_pwm *mc33xs2410)
+{
+	struct device *dev = &mc33xs2410->spi->dev;
+	u16 di_en = 0;
+	char buf[4];
+	int ret, ch;
+
+	for (ch = 0; ch < 4; ch++) {
+		sprintf(buf, "di%d", ch);
+		mc33xs2410->di[ch] = devm_pwm_get(dev, buf);
+		ret = PTR_ERR_OR_ZERO(mc33xs2410->di[ch]);
+		switch (ret) {
+		case 0:
+			di_en |= MC33XS2410_IN_CTRL1_IN_EN(ch);
+			break;
+		case -ENODATA:
+			mc33xs2410->di[ch] = NULL;
+			break;
+		case -EPROBE_DEFER:
+			return ret;
+		default:
+			dev_err(dev, "Failed to request %s: %d\n", buf, ret);
+			return ret;
+		}
+	}
+
+	if (!di_en)
+		return 0;
+
+	/* CMOS input logic level */
+	ret = mc33xs2410_modify_reg(mc33xs2410->spi, MC33XS2410_GLB_CTRL,
+				    MC33XS2410_GLB_CTRL_CMOS_LEVEL,
+				    MC33XS2410_GLB_CTRL_CMOS_LEVEL);
+	if (ret < 0)
+		return ret;
+
+	return mc33xs2410_write_reg(mc33xs2410->spi, MC33XS2410_IN_CTRL1, di_en);
+}
+
 static int mc33xs2410_probe(struct spi_device *spi)
 {
 	struct mc33xs2410_pwm *mc33xs2410;
@@ -290,6 +379,11 @@ static int mc33xs2410_probe(struct spi_device *spi)
 		return dev_err_probe(dev, ret,
 				     "Failed to transition to normal mode\n");
 
+	/* Enable direct inputs */
+	ret = mc33xs2410_direct_inputs_probe(mc33xs2410);
+	if (ret)
+		return ret;
+
 	ret = devm_pwmchip_add(dev, &mc33xs2410->chip);
 	if (ret < 0)
 		return dev_err_probe(dev, ret, "Failed to add pwm chip\n");
-- 
2.39.2


Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ