@@ -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");