[PATCH v1 6/6] pwm: tegra: Implement .get_state()
Uwe Kleine-König <[email protected]> Tue, 14 Jul 2026 14:02:40 +0200
| Newsgroups | org.kernel.vger.linux-pwm,org.kernel.vger.linux-tegra |
|---|---|
| Message-ID | <33b13f17d7135923d08e2ff40c867803e19609b9.1784030076.git.ukleinek@kernel.org> |
The registers of the PWM IP are readable. Use that to implement the .get_state() callback. Signed-off-by: Uwe Kleine-König <[email protected]> --- 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 8e5e7e37f4ff..79bfc7589db8 100644 --- a/drivers/pwm/pwm-tegra.c +++ b/drivers/pwm/pwm-tegra.c @@ -309,8 +309,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.55.0.11.g153666a7d9bb