aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAjit Pal Singh <ajitpal.singh@st.com>2014-07-14 10:33:29 -0400
committerThierry Reding <thierry.reding@gmail.com>2014-08-08 07:12:40 -0400
commitbf9cc80b6c3ec2754b570d377ed7f7e2ec96868a (patch)
tree181ee5621900f4a370bd4f9cab515fa2f8602bcf
parentacad00d3d67ef2a7177beb70e7aeef5f0bd2bcf0 (diff)
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: Ajit Pal Singh <ajitpal.singh@st.com> Signed-off-by: Lee Jones <lee.jones@linaro.org> Signed-off-by: Thierry Reding <thierry.reding@gmail.com>
-rw-r--r--drivers/pwm/pwm-sti.c38
1 files changed, 27 insertions, 11 deletions
diff --git a/drivers/pwm/pwm-sti.c b/drivers/pwm/pwm-sti.c
index 0b714e45e5c0..76346e32f403 100644
--- a/drivers/pwm/pwm-sti.c
+++ b/drivers/pwm/pwm-sti.c
@@ -25,10 +25,13 @@
25#define STI_DS_REG(ch) (4 * (ch)) /* Channel's Duty Cycle register */ 25#define STI_DS_REG(ch) (4 * (ch)) /* Channel's Duty Cycle register */
26#define STI_PWMCR 0x50 /* Control/Config register */ 26#define STI_PWMCR 0x50 /* Control/Config register */
27#define STI_INTEN 0x54 /* Interrupt Enable/Disable register */ 27#define STI_INTEN 0x54 /* Interrupt Enable/Disable register */
28#define PWM_PRESCALE_LOW_MASK 0x0f
29#define PWM_PRESCALE_HIGH_MASK 0xf0
28 30
29/* Regfield IDs */ 31/* Regfield IDs */
30enum { 32enum {
31 PWMCLK_PRESCALE, 33 PWMCLK_PRESCALE_LOW,
34 PWMCLK_PRESCALE_HIGH,
32 PWM_EN, 35 PWM_EN,
33 PWM_INT_EN, 36 PWM_INT_EN,
34 37
@@ -49,7 +52,8 @@ struct sti_pwm_chip {
49 unsigned long clk_rate; 52 unsigned long clk_rate;
50 struct regmap *regmap; 53 struct regmap *regmap;
51 struct sti_pwm_compat_data *cdata; 54 struct sti_pwm_compat_data *cdata;
52 struct regmap_field *prescale; 55 struct regmap_field *prescale_low;
56 struct regmap_field *prescale_high;
53 struct regmap_field *pwm_en; 57 struct regmap_field *pwm_en;
54 struct regmap_field *pwm_int_en; 58 struct regmap_field *pwm_int_en;
55 unsigned long *pwm_periods; 59 unsigned long *pwm_periods;
@@ -58,7 +62,8 @@ struct sti_pwm_chip {
58}; 62};
59 63
60static const struct reg_field sti_pwm_regfields[MAX_REGFIELDS] = { 64static const struct reg_field sti_pwm_regfields[MAX_REGFIELDS] = {
61 [PWMCLK_PRESCALE] = REG_FIELD(STI_PWMCR, 0, 3), 65 [PWMCLK_PRESCALE_LOW] = REG_FIELD(STI_PWMCR, 0, 3),
66 [PWMCLK_PRESCALE_HIGH] = REG_FIELD(STI_PWMCR, 11, 14),
62 [PWM_EN] = REG_FIELD(STI_PWMCR, 9, 9), 67 [PWM_EN] = REG_FIELD(STI_PWMCR, 9, 9),
63 [PWM_INT_EN] = REG_FIELD(STI_INTEN, 0, 0), 68 [PWM_INT_EN] = REG_FIELD(STI_INTEN, 0, 0),
64}; 69};
@@ -109,10 +114,10 @@ static int sti_pwm_cmp_periods(const void *key, const void *elt)
109 * For STiH4xx PWM IP, the PWM period is fixed to 256 local clock cycles. 114 * For STiH4xx PWM IP, the PWM period is fixed to 256 local clock cycles.
110 * The only way to change the period (apart from changing the PWM input clock) 115 * The only way to change the period (apart from changing the PWM input clock)
111 * is to change the PWM clock prescaler. 116 * is to change the PWM clock prescaler.
112 * The prescaler is of 4 bits, so only 16 prescaler values and hence only 117 * The prescaler is of 8 bits, so 256 prescaler values and hence
113 * 16 possible period values are supported (for a particular clock rate). 118 * 256 possible period values are supported (for a particular clock rate).
114 * The requested period will be applied only if it matches one of these 119 * The requested period will be applied only if it matches one of these
115 * 16 values. 120 * 256 values.
116 */ 121 */
117static int sti_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, 122static int sti_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
118 int duty_ns, int period_ns) 123 int duty_ns, int period_ns)
@@ -154,7 +159,13 @@ static int sti_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
154 if (ret) 159 if (ret)
155 return ret; 160 return ret;
156 161
157 ret = regmap_field_write(pc->prescale, prescale); 162 ret = regmap_field_write(pc->prescale_low,
163 prescale & PWM_PRESCALE_LOW_MASK);
164 if (ret)
165 goto clk_dis;
166
167 ret = regmap_field_write(pc->prescale_high,
168 (prescale & PWM_PRESCALE_HIGH_MASK) >> 4);
158 if (ret) 169 if (ret)
159 goto clk_dis; 170 goto clk_dis;
160 171
@@ -222,10 +233,15 @@ static int sti_pwm_probe_dt(struct sti_pwm_chip *pc)
222 233
223 reg_fields = cdata->reg_fields; 234 reg_fields = cdata->reg_fields;
224 235
225 pc->prescale = devm_regmap_field_alloc(dev, pc->regmap, 236 pc->prescale_low = devm_regmap_field_alloc(dev, pc->regmap,
226 reg_fields[PWMCLK_PRESCALE]); 237 reg_fields[PWMCLK_PRESCALE_LOW]);
227 if (IS_ERR(pc->prescale)) 238 if (IS_ERR(pc->prescale_low))
228 return PTR_ERR(pc->prescale); 239 return PTR_ERR(pc->prescale_low);
240
241 pc->prescale_high = devm_regmap_field_alloc(dev, pc->regmap,
242 reg_fields[PWMCLK_PRESCALE_HIGH]);
243 if (IS_ERR(pc->prescale_high))
244 return PTR_ERR(pc->prescale_high);
229 245
230 pc->pwm_en = devm_regmap_field_alloc(dev, pc->regmap, 246 pc->pwm_en = devm_regmap_field_alloc(dev, pc->regmap,
231 reg_fields[PWM_EN]); 247 reg_fields[PWM_EN]);