diff options
author | Ajit Pal Singh <ajitpal.singh@st.com> | 2014-07-14 10:33:29 -0400 |
---|---|---|
committer | Thierry Reding <thierry.reding@gmail.com> | 2014-08-08 07:12:40 -0400 |
commit | bf9cc80b6c3ec2754b570d377ed7f7e2ec96868a (patch) | |
tree | 181ee5621900f4a370bd4f9cab515fa2f8602bcf | |
parent | acad00d3d67ef2a7177beb70e7aeef5f0bd2bcf0 (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.c | 38 |
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 */ |
30 | enum { | 32 | enum { |
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 | ||
60 | static const struct reg_field sti_pwm_regfields[MAX_REGFIELDS] = { | 64 | static 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 | */ |
117 | static int sti_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, | 122 | static 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]); |