Commit 651b510a authored by Uwe Kleine-König's avatar Uwe Kleine-König Committed by Thierry Reding
Browse files

pwm: atmel: Implement .get_state()



This function reads back the configured parameters from the hardware. As
.apply() rounds down (mostly) I'm rounding up in .get_state() to achieve
that applying a state just read from hardware is a no-op.

Signed-off-by: default avatarUwe Kleine-König <uwe@kleine-koenig.org>
Acked-by: default avatarClaudiu Beznea <claudiu.beznea@microchip.com>
Signed-off-by: default avatarThierry Reding <thierry.reding@gmail.com>
parent 02afb811
Loading
Loading
Loading
Loading
+40 −0
Original line number Diff line number Diff line
@@ -295,8 +295,48 @@ static int atmel_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
	return 0;
}

static void atmel_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm,
				struct pwm_state *state)
{
	struct atmel_pwm_chip *atmel_pwm = to_atmel_pwm_chip(chip);
	u32 sr, cmr;

	sr = atmel_pwm_readl(atmel_pwm, PWM_SR);
	cmr = atmel_pwm_ch_readl(atmel_pwm, pwm->hwpwm, PWM_CMR);

	if (sr & (1 << pwm->hwpwm)) {
		unsigned long rate = clk_get_rate(atmel_pwm->clk);
		u32 cdty, cprd, pres;
		u64 tmp;

		pres = cmr & PWM_CMR_CPRE_MSK;

		cprd = atmel_pwm_ch_readl(atmel_pwm, pwm->hwpwm,
					  atmel_pwm->data->regs.period);
		tmp = (u64)cprd * NSEC_PER_SEC;
		tmp <<= pres;
		state->period = DIV64_U64_ROUND_UP(tmp, rate);

		cdty = atmel_pwm_ch_readl(atmel_pwm, pwm->hwpwm,
					  atmel_pwm->data->regs.duty);
		tmp = (u64)cdty * NSEC_PER_SEC;
		tmp <<= pres;
		state->duty_cycle = DIV64_U64_ROUND_UP(tmp, rate);

		state->enabled = true;
	} else {
		state->enabled = false;
	}

	if (cmr & PWM_CMR_CPOL)
		state->polarity = PWM_POLARITY_INVERSED;
	else
		state->polarity = PWM_POLARITY_NORMAL;
}

static const struct pwm_ops atmel_pwm_ops = {
	.apply = atmel_pwm_apply,
	.get_state = atmel_pwm_get_state,
	.owner = THIS_MODULE,
};