[PATCH v2 3/3] pwm: tegra: Implement .get_state()
From: Uwe Kleine-König
Date: Fri Sep 18 2026 - 11:53:56 EST
The registers of the PWM IP are readable. Use that to implement the
.get_state() callback.
Reviewed-by: Mikko Perttunen <mperttunen@xxxxxxxxxx>
Tested-by: Ola Chr. Vaage <ola.christoffer.vage@xxxxxxxxxxx>
Signed-off-by: Uwe Kleine-König <u.kleine-koenig@xxxxxxxxxxxx>
---
drivers/pwm/pwm-tegra.c | 48 +++++++++++++++++++++++++++++++++++++++++
1 file changed, 48 insertions(+)
diff --git a/drivers/pwm/pwm-tegra.c b/drivers/pwm/pwm-tegra.c
index b461d3877f43..0520d025c776 100644
--- a/drivers/pwm/pwm-tegra.c
+++ b/drivers/pwm/pwm-tegra.c
@@ -310,8 +310,56 @@ static int tegra_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
return err;
}
+static int tegra_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm,
+ struct pwm_state *state)
+{
+ struct tegra_pwm_chip *pc = to_tegra_pwm_chip(chip);
+ int rc;
+ u32 val;
+
+ rc = pm_runtime_resume_and_get(pwmchip_parent(chip));
+ if (rc)
+ return rc;
+
+ val = tegra_pwm_readl(pwm, pc->soc->enable_reg);
+ if (val & TEGRA_PWM_ENABLE) {
+ u32 scale, pwm0;
+
+ if (pc->soc->enable_reg != TEGRA_PWM_CSR_0)
+ val = tegra_pwm_readl(pwm, TEGRA_PWM_CSR_0);
+
+ scale = (val >> TEGRA_PWM_SCALE_SHIFT) & ((1 << pc->soc->scale_width) - 1);
+ pwm0 = (val >> TEGRA_PWM_DUTY_SHIFT) & (2 * TEGRA_PWM_DEPTH - 1);
+
+ if (pwm0 > TEGRA_PWM_DEPTH)
+ pwm0 = TEGRA_PWM_DEPTH;
+
+ /*
+ * scale + 1 is at most 1 << 17, TEGRA_PWM_DEPTH is 256, so the
+ * multiplication for .period doesn't overflow a u64. With
+ * pwm0 ≤ TEGRA_PWM_DEPTH, .duty_cycle is also fine.
+ */
+ *state = (struct pwm_state){
+ .period = DIV64_U64_ROUND_UP((u64)(scale + 1) * TEGRA_PWM_DEPTH * NSEC_PER_SEC, pc->clk_rate),
+ .duty_cycle = DIV64_U64_ROUND_UP((u64)(scale + 1) * pwm0 * NSEC_PER_SEC, pc->clk_rate),
+ .polarity = PWM_POLARITY_NORMAL,
+ .enabled = true,
+ };
+
+ } else {
+ *state = (struct pwm_state){
+ .enabled = false,
+ };
+ }
+
+ pm_runtime_put(pwmchip_parent(chip));
+
+ return 0;
+}
+
static const struct pwm_ops tegra_pwm_ops = {
.apply = tegra_pwm_apply,
+ .get_state = tegra_pwm_get_state,
};
static int tegra_pwm_probe(struct platform_device *pdev)
--
2.47.3