Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit bf9cc80b authored by Ajit Pal Singh's avatar Ajit Pal Singh Committed by Thierry Reding
Browse files

pwm: sti: Fix PWM prescaler handling



This patch fixes the pwm driver to write the complete 8 bits of
the prescaler value to the PWM Control register.

Signed-off-by: default avatarAjit Pal Singh <ajitpal.singh@st.com>
Signed-off-by: default avatarLee Jones <lee.jones@linaro.org>
Signed-off-by: default avatarThierry Reding <thierry.reding@gmail.com>
parent acad00d3
Loading
Loading
Loading
Loading
+27 −11
Original line number Diff line number Diff line
@@ -25,10 +25,13 @@
#define STI_DS_REG(ch)	(4 * (ch))	/* Channel's Duty Cycle register */
#define STI_PWMCR	0x50		/* Control/Config register */
#define STI_INTEN	0x54		/* Interrupt Enable/Disable register */
#define PWM_PRESCALE_LOW_MASK		0x0f
#define PWM_PRESCALE_HIGH_MASK		0xf0

/* Regfield IDs */
enum {
	PWMCLK_PRESCALE,
	PWMCLK_PRESCALE_LOW,
	PWMCLK_PRESCALE_HIGH,
	PWM_EN,
	PWM_INT_EN,

@@ -49,7 +52,8 @@ struct sti_pwm_chip {
	unsigned long clk_rate;
	struct regmap *regmap;
	struct sti_pwm_compat_data *cdata;
	struct regmap_field *prescale;
	struct regmap_field *prescale_low;
	struct regmap_field *prescale_high;
	struct regmap_field *pwm_en;
	struct regmap_field *pwm_int_en;
	unsigned long *pwm_periods;
@@ -58,7 +62,8 @@ struct sti_pwm_chip {
};

static const struct reg_field sti_pwm_regfields[MAX_REGFIELDS] = {
	[PWMCLK_PRESCALE]	= REG_FIELD(STI_PWMCR, 0, 3),
	[PWMCLK_PRESCALE_LOW]	= REG_FIELD(STI_PWMCR, 0, 3),
	[PWMCLK_PRESCALE_HIGH]	= REG_FIELD(STI_PWMCR, 11, 14),
	[PWM_EN]		= REG_FIELD(STI_PWMCR, 9, 9),
	[PWM_INT_EN]		= REG_FIELD(STI_INTEN, 0, 0),
};
@@ -109,10 +114,10 @@ static int sti_pwm_cmp_periods(const void *key, const void *elt)
 * For STiH4xx PWM IP, the PWM period is fixed to 256 local clock cycles.
 * The only way to change the period (apart from changing the PWM input clock)
 * is to change the PWM clock prescaler.
 * The prescaler is of 4 bits, so only 16 prescaler values and hence only
 * 16 possible period values are supported (for a particular clock rate).
 * The prescaler is of 8 bits, so 256 prescaler values and hence
 * 256 possible period values are supported (for a particular clock rate).
 * The requested period will be applied only if it matches one of these
 * 16 values.
 * 256 values.
 */
static int sti_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
			 int duty_ns, int period_ns)
@@ -154,7 +159,13 @@ static int sti_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
	if (ret)
		return ret;

	ret = regmap_field_write(pc->prescale, prescale);
	ret = regmap_field_write(pc->prescale_low,
				 prescale & PWM_PRESCALE_LOW_MASK);
	if (ret)
		goto clk_dis;

	ret = regmap_field_write(pc->prescale_high,
				 (prescale & PWM_PRESCALE_HIGH_MASK) >> 4);
	if (ret)
		goto clk_dis;

@@ -222,10 +233,15 @@ static int sti_pwm_probe_dt(struct sti_pwm_chip *pc)

	reg_fields = cdata->reg_fields;

	pc->prescale = devm_regmap_field_alloc(dev, pc->regmap,
					       reg_fields[PWMCLK_PRESCALE]);
	if (IS_ERR(pc->prescale))
		return PTR_ERR(pc->prescale);
	pc->prescale_low = devm_regmap_field_alloc(dev, pc->regmap,
					reg_fields[PWMCLK_PRESCALE_LOW]);
	if (IS_ERR(pc->prescale_low))
		return PTR_ERR(pc->prescale_low);

	pc->prescale_high = devm_regmap_field_alloc(dev, pc->regmap,
					reg_fields[PWMCLK_PRESCALE_HIGH]);
	if (IS_ERR(pc->prescale_high))
		return PTR_ERR(pc->prescale_high);

	pc->pwm_en = devm_regmap_field_alloc(dev, pc->regmap,
					     reg_fields[PWM_EN]);