diff options
author | Lee Jones <lee.jones@linaro.org> | 2016-08-16 05:35:07 -0400 |
---|---|---|
committer | Thierry Reding <thierry.reding@gmail.com> | 2016-09-08 04:55:12 -0400 |
commit | 7d8a600c916cab347662de212340d3eaf0e93db2 (patch) | |
tree | f3c29f24517810af259f03d1dee1e93663179677 | |
parent | 85a834c42a491deed9ac5bca549b93b7a5455d84 (diff) |
pwm: sti: Take the opportunity to conduct a little house keeping
This includes fixing some Coding Style issues and re-ordering and/or
simplifying a little code.
Signed-off-by: Lee Jones <lee.jones@linaro.org>
[thierry.reding@gmail.com: applied some bikeshedding>
Signed-off-by: Thierry Reding <thierry.reding@gmail.com>
-rw-r--r-- | drivers/pwm/pwm-sti.c | 153 |
1 files changed, 81 insertions, 72 deletions
diff --git a/drivers/pwm/pwm-sti.c b/drivers/pwm/pwm-sti.c index 9a1ca1986c30..dd82dc840af9 100644 --- a/drivers/pwm/pwm-sti.c +++ b/drivers/pwm/pwm-sti.c | |||
@@ -1,8 +1,10 @@ | |||
1 | /* | 1 | /* |
2 | * PWM device driver for ST SoCs. | 2 | * PWM device driver for ST SoCs |
3 | * Author: Ajit Pal Singh <ajitpal.singh@st.com> | 3 | * |
4 | * Copyright (C) 2013-2016 STMicroelectronics (R&D) Limited | ||
4 | * | 5 | * |
5 | * Copyright (C) 2013-2014 STMicroelectronics (R&D) Limited | 6 | * Author: Ajit Pal Singh <ajitpal.singh@st.com> |
7 | * Lee Jones <lee.jones@linaro.org> | ||
6 | * | 8 | * |
7 | * This program is free software; you can redistribute it and/or modify | 9 | * This program is free software; you can redistribute it and/or modify |
8 | * it under the terms of the GNU General Public License as published by | 10 | * it under the terms of the GNU General Public License as published by |
@@ -31,14 +33,14 @@ | |||
31 | #define STI_PWM_CTRL 0x50 /* Control/Config register */ | 33 | #define STI_PWM_CTRL 0x50 /* Control/Config register */ |
32 | #define STI_INT_EN 0x54 /* Interrupt Enable/Disable register */ | 34 | #define STI_INT_EN 0x54 /* Interrupt Enable/Disable register */ |
33 | #define STI_INT_STA 0x58 /* Interrupt Status register */ | 35 | #define STI_INT_STA 0x58 /* Interrupt Status register */ |
34 | #define PWM_INT_ACK 0x5c | 36 | #define PWM_INT_ACK 0x5c |
35 | #define PWM_PRESCALE_LOW_MASK 0x0f | 37 | #define PWM_PRESCALE_LOW_MASK 0x0f |
36 | #define PWM_PRESCALE_HIGH_MASK 0xf0 | 38 | #define PWM_PRESCALE_HIGH_MASK 0xf0 |
37 | #define PWM_CPT_EDGE_MASK 0x03 | 39 | #define PWM_CPT_EDGE_MASK 0x03 |
38 | #define PWM_INT_ACK_MASK 0x1ff | 40 | #define PWM_INT_ACK_MASK 0x1ff |
39 | 41 | ||
40 | #define STI_MAX_CPT_DEVS 4 | 42 | #define STI_MAX_CPT_DEVS 4 |
41 | #define CPT_DC_MAX 0xff | 43 | #define CPT_DC_MAX 0xff |
42 | 44 | ||
43 | /* Regfield IDs */ | 45 | /* Regfield IDs */ |
44 | enum { | 46 | enum { |
@@ -57,8 +59,9 @@ enum { | |||
57 | MAX_REGFIELDS | 59 | MAX_REGFIELDS |
58 | }; | 60 | }; |
59 | 61 | ||
60 | /* Each capture input can be programmed to detect rising-edge, falling-edge, | 62 | /* |
61 | * either edge or neither egde | 63 | * Each capture input can be programmed to detect rising-edge, falling-edge, |
64 | * either edge or neither egde. | ||
62 | */ | 65 | */ |
63 | enum sti_cpt_edge { | 66 | enum sti_cpt_edge { |
64 | CPT_EDGE_DISABLED, | 67 | CPT_EDGE_DISABLED, |
@@ -103,13 +106,13 @@ struct sti_pwm_chip { | |||
103 | }; | 106 | }; |
104 | 107 | ||
105 | static const struct reg_field sti_pwm_regfields[MAX_REGFIELDS] = { | 108 | static const struct reg_field sti_pwm_regfields[MAX_REGFIELDS] = { |
106 | [PWMCLK_PRESCALE_LOW] = REG_FIELD(STI_PWM_CTRL, 0, 3), | 109 | [PWMCLK_PRESCALE_LOW] = REG_FIELD(STI_PWM_CTRL, 0, 3), |
107 | [PWMCLK_PRESCALE_HIGH] = REG_FIELD(STI_PWM_CTRL, 11, 14), | 110 | [PWMCLK_PRESCALE_HIGH] = REG_FIELD(STI_PWM_CTRL, 11, 14), |
108 | [CPTCLK_PRESCALE] = REG_FIELD(STI_PWM_CTRL, 4, 8), | 111 | [CPTCLK_PRESCALE] = REG_FIELD(STI_PWM_CTRL, 4, 8), |
109 | [PWM_OUT_EN] = REG_FIELD(STI_PWM_CTRL, 9, 9), | 112 | [PWM_OUT_EN] = REG_FIELD(STI_PWM_CTRL, 9, 9), |
110 | [PWM_CPT_EN] = REG_FIELD(STI_PWM_CTRL, 10, 10), | 113 | [PWM_CPT_EN] = REG_FIELD(STI_PWM_CTRL, 10, 10), |
111 | [PWM_CPT_INT_EN] = REG_FIELD(STI_INT_EN, 1, 4), | 114 | [PWM_CPT_INT_EN] = REG_FIELD(STI_INT_EN, 1, 4), |
112 | [PWM_CPT_INT_STAT] = REG_FIELD(STI_INT_STA, 1, 4), | 115 | [PWM_CPT_INT_STAT] = REG_FIELD(STI_INT_STA, 1, 4), |
113 | }; | 116 | }; |
114 | 117 | ||
115 | static inline struct sti_pwm_chip *to_sti_pwmchip(struct pwm_chip *chip) | 118 | static inline struct sti_pwm_chip *to_sti_pwmchip(struct pwm_chip *chip) |
@@ -125,7 +128,7 @@ static int sti_pwm_get_prescale(struct sti_pwm_chip *pc, unsigned long period, | |||
125 | { | 128 | { |
126 | struct sti_pwm_compat_data *cdata = pc->cdata; | 129 | struct sti_pwm_compat_data *cdata = pc->cdata; |
127 | unsigned long clk_rate; | 130 | unsigned long clk_rate; |
128 | unsigned long val; | 131 | unsigned long value; |
129 | unsigned int ps; | 132 | unsigned int ps; |
130 | 133 | ||
131 | clk_rate = clk_get_rate(pc->pwm_clk); | 134 | clk_rate = clk_get_rate(pc->pwm_clk); |
@@ -135,56 +138,56 @@ static int sti_pwm_get_prescale(struct sti_pwm_chip *pc, unsigned long period, | |||
135 | } | 138 | } |
136 | 139 | ||
137 | /* | 140 | /* |
138 | * prescale = ((period_ns * clk_rate) / (10^9 * (max_pwm_count + 1)) - 1 | 141 | * prescale = ((period_ns * clk_rate) / (10^9 * (max_pwm_cnt + 1)) - 1 |
139 | */ | 142 | */ |
140 | val = NSEC_PER_SEC / clk_rate; | 143 | value = NSEC_PER_SEC / clk_rate; |
141 | val *= cdata->max_pwm_cnt + 1; | 144 | value *= cdata->max_pwm_cnt + 1; |
142 | 145 | ||
143 | if (period % val) { | 146 | if (period % value) |
144 | return -EINVAL; | 147 | return -EINVAL; |
145 | } else { | 148 | |
146 | ps = period / val - 1; | 149 | ps = period / value - 1; |
147 | if (ps > cdata->max_prescale) | 150 | if (ps > cdata->max_prescale) |
148 | return -EINVAL; | 151 | return -EINVAL; |
149 | } | 152 | |
150 | *prescale = ps; | 153 | *prescale = ps; |
151 | 154 | ||
152 | return 0; | 155 | return 0; |
153 | } | 156 | } |
154 | 157 | ||
155 | /* | 158 | /* |
156 | * For STiH4xx PWM IP, the PWM period is fixed to 256 local clock cycles. | 159 | * For STiH4xx PWM IP, the PWM period is fixed to 256 local clock cycles. The |
157 | * The only way to change the period (apart from changing the PWM input clock) | 160 | * only way to change the period (apart from changing the PWM input clock) is |
158 | * is to change the PWM clock prescaler. | 161 | * to change the PWM clock prescaler. |
159 | * The prescaler is of 8 bits, so 256 prescaler values and hence | 162 | * |
160 | * 256 possible period values are supported (for a particular clock rate). | 163 | * The prescaler is of 8 bits, so 256 prescaler values and hence 256 possible |
161 | * The requested period will be applied only if it matches one of these | 164 | * period values are supported (for a particular clock rate). The requested |
162 | * 256 values. | 165 | * period will be applied only if it matches one of these 256 values. |
163 | */ | 166 | */ |
164 | static int sti_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, | 167 | static int sti_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, |
165 | int duty_ns, int period_ns) | 168 | int duty_ns, int period_ns) |
166 | { | 169 | { |
167 | struct sti_pwm_chip *pc = to_sti_pwmchip(chip); | 170 | struct sti_pwm_chip *pc = to_sti_pwmchip(chip); |
168 | struct sti_pwm_compat_data *cdata = pc->cdata; | 171 | struct sti_pwm_compat_data *cdata = pc->cdata; |
172 | unsigned int ncfg, value, prescale = 0; | ||
169 | struct pwm_device *cur = pc->cur; | 173 | struct pwm_device *cur = pc->cur; |
170 | struct device *dev = pc->dev; | 174 | struct device *dev = pc->dev; |
171 | unsigned int prescale = 0, pwmvalx; | ||
172 | int ret; | ||
173 | unsigned int ncfg; | ||
174 | bool period_same = false; | 175 | bool period_same = false; |
176 | int ret; | ||
175 | 177 | ||
176 | ncfg = hweight_long(pc->configured); | 178 | ncfg = hweight_long(pc->configured); |
177 | if (ncfg) | 179 | if (ncfg) |
178 | period_same = (period_ns == pwm_get_period(cur)); | 180 | period_same = (period_ns == pwm_get_period(cur)); |
179 | 181 | ||
180 | /* Allow configuration changes if one of the | 182 | /* |
181 | * following conditions satisfy. | 183 | * Allow configuration changes if one of the following conditions |
184 | * satisfy. | ||
182 | * 1. No devices have been configured. | 185 | * 1. No devices have been configured. |
183 | * 2. Only one device has been configured and the new request | 186 | * 2. Only one device has been configured and the new request is for |
184 | * is for the same device. | 187 | * the same device. |
185 | * 3. Only one device has been configured and the new request is | 188 | * 3. Only one device has been configured and the new request is for |
186 | * for a new device and period of the new device is same as | 189 | * a new device and period of the new device is same as the current |
187 | * the current configured period. | 190 | * configured period. |
188 | * 4. More than one devices are configured and period of the new | 191 | * 4. More than one devices are configured and period of the new |
189 | * requestis the same as the current period. | 192 | * requestis the same as the current period. |
190 | */ | 193 | */ |
@@ -206,15 +209,15 @@ static int sti_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, | |||
206 | if (ret) | 209 | if (ret) |
207 | goto clk_dis; | 210 | goto clk_dis; |
208 | 211 | ||
209 | ret = | 212 | value = prescale & PWM_PRESCALE_LOW_MASK; |
210 | regmap_field_write(pc->prescale_low, | 213 | |
211 | prescale & PWM_PRESCALE_LOW_MASK); | 214 | ret = regmap_field_write(pc->prescale_low, value); |
212 | if (ret) | 215 | if (ret) |
213 | goto clk_dis; | 216 | goto clk_dis; |
214 | 217 | ||
215 | ret = | 218 | value = (prescale & PWM_PRESCALE_HIGH_MASK) >> 4; |
216 | regmap_field_write(pc->prescale_high, | 219 | |
217 | (prescale & PWM_PRESCALE_HIGH_MASK) >> 4); | 220 | ret = regmap_field_write(pc->prescale_high, value); |
218 | if (ret) | 221 | if (ret) |
219 | goto clk_dis; | 222 | goto clk_dis; |
220 | } | 223 | } |
@@ -225,10 +228,9 @@ static int sti_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, | |||
225 | * PWM pulse = (max_pwm_count + 1) local cycles, | 228 | * PWM pulse = (max_pwm_count + 1) local cycles, |
226 | * that is continuous pulse: signal never goes low. | 229 | * that is continuous pulse: signal never goes low. |
227 | */ | 230 | */ |
228 | pwmvalx = cdata->max_pwm_cnt * duty_ns / period_ns; | 231 | value = cdata->max_pwm_cnt * duty_ns / period_ns; |
229 | 232 | ||
230 | ret = regmap_write(pc->regmap, | 233 | ret = regmap_write(pc->regmap, PWM_OUT_VAL(pwm->hwpwm), value); |
231 | PWM_OUT_VAL(pwm->hwpwm), pwmvalx); | ||
232 | if (ret) | 234 | if (ret) |
233 | goto clk_dis; | 235 | goto clk_dis; |
234 | 236 | ||
@@ -237,8 +239,8 @@ static int sti_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, | |||
237 | set_bit(pwm->hwpwm, &pc->configured); | 239 | set_bit(pwm->hwpwm, &pc->configured); |
238 | pc->cur = pwm; | 240 | pc->cur = pwm; |
239 | 241 | ||
240 | dev_dbg(dev, "prescale:%u, period:%i, duty:%i, pwmvalx:%u\n", | 242 | dev_dbg(dev, "prescale:%u, period:%i, duty:%i, value:%u\n", |
241 | prescale, period_ns, duty_ns, pwmvalx); | 243 | prescale, period_ns, duty_ns, value); |
242 | } else { | 244 | } else { |
243 | return -EINVAL; | 245 | return -EINVAL; |
244 | } | 246 | } |
@@ -256,10 +258,11 @@ static int sti_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm) | |||
256 | int ret = 0; | 258 | int ret = 0; |
257 | 259 | ||
258 | /* | 260 | /* |
259 | * Since we have a common enable for all PWM devices, | 261 | * Since we have a common enable for all PWM devices, do not enable if |
260 | * do not enable if already enabled. | 262 | * already enabled. |
261 | */ | 263 | */ |
262 | mutex_lock(&pc->sti_pwm_lock); | 264 | mutex_lock(&pc->sti_pwm_lock); |
265 | |||
263 | if (!pc->en_count) { | 266 | if (!pc->en_count) { |
264 | ret = clk_enable(pc->pwm_clk); | 267 | ret = clk_enable(pc->pwm_clk); |
265 | if (ret) | 268 | if (ret) |
@@ -271,12 +274,14 @@ static int sti_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm) | |||
271 | 274 | ||
272 | ret = regmap_field_write(pc->pwm_out_en, 1); | 275 | ret = regmap_field_write(pc->pwm_out_en, 1); |
273 | if (ret) { | 276 | if (ret) { |
274 | dev_err(dev, "failed to enable PWM device:%d\n", | 277 | dev_err(dev, "failed to enable PWM device %u: %d\n", |
275 | pwm->hwpwm); | 278 | pwm->hwpwm, ret); |
276 | goto out; | 279 | goto out; |
277 | } | 280 | } |
278 | } | 281 | } |
282 | |||
279 | pc->en_count++; | 283 | pc->en_count++; |
284 | |||
280 | out: | 285 | out: |
281 | mutex_unlock(&pc->sti_pwm_lock); | 286 | mutex_unlock(&pc->sti_pwm_lock); |
282 | return ret; | 287 | return ret; |
@@ -287,14 +292,17 @@ static void sti_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm) | |||
287 | struct sti_pwm_chip *pc = to_sti_pwmchip(chip); | 292 | struct sti_pwm_chip *pc = to_sti_pwmchip(chip); |
288 | 293 | ||
289 | mutex_lock(&pc->sti_pwm_lock); | 294 | mutex_lock(&pc->sti_pwm_lock); |
295 | |||
290 | if (--pc->en_count) { | 296 | if (--pc->en_count) { |
291 | mutex_unlock(&pc->sti_pwm_lock); | 297 | mutex_unlock(&pc->sti_pwm_lock); |
292 | return; | 298 | return; |
293 | } | 299 | } |
300 | |||
294 | regmap_field_write(pc->pwm_out_en, 0); | 301 | regmap_field_write(pc->pwm_out_en, 0); |
295 | 302 | ||
296 | clk_disable(pc->pwm_clk); | 303 | clk_disable(pc->pwm_clk); |
297 | clk_disable(pc->cpt_clk); | 304 | clk_disable(pc->cpt_clk); |
305 | |||
298 | mutex_unlock(&pc->sti_pwm_lock); | 306 | mutex_unlock(&pc->sti_pwm_lock); |
299 | } | 307 | } |
300 | 308 | ||
@@ -422,14 +430,13 @@ static irqreturn_t sti_pwm_interrupt(int irq, void *data) | |||
422 | * __| |_________________| |________ | 430 | * __| |_________________| |________ |
423 | * ^0 ^1 ^2 | 431 | * ^0 ^1 ^2 |
424 | * | 432 | * |
425 | * Capture start by the first available rising edge | 433 | * Capture start by the first available rising edge. When a |
426 | * When a capture event occurs, capture value (CPT_VALx) | 434 | * capture event occurs, capture value (CPT_VALx) is stored, |
427 | * is stored, index incremented, capture edge changed. | 435 | * index incremented, capture edge changed. |
428 | * | ||
429 | * After the capture, if the index > 1, we have collected | ||
430 | * the necessary data so we signal the thread waiting for it | ||
431 | * and disable the capture by setting capture edge to none | ||
432 | * | 436 | * |
437 | * After the capture, if the index > 1, we have collected the | ||
438 | * necessary data so we signal the thread waiting for it and | ||
439 | * disable the capture by setting capture edge to none | ||
433 | */ | 440 | */ |
434 | 441 | ||
435 | regmap_read(pc->regmap, | 442 | regmap_read(pc->regmap, |
@@ -445,12 +452,14 @@ static irqreturn_t sti_pwm_interrupt(int irq, void *data) | |||
445 | 452 | ||
446 | ddata->index++; | 453 | ddata->index++; |
447 | break; | 454 | break; |
455 | |||
448 | case 2: | 456 | case 2: |
449 | regmap_write(pc->regmap, | 457 | regmap_write(pc->regmap, |
450 | PWM_CPT_EDGE(devicenum), | 458 | PWM_CPT_EDGE(devicenum), |
451 | CPT_EDGE_DISABLED); | 459 | CPT_EDGE_DISABLED); |
452 | wake_up(&ddata->wait); | 460 | wake_up(&ddata->wait); |
453 | break; | 461 | break; |
462 | |||
454 | default: | 463 | default: |
455 | dev_err(dev, "Internal error\n"); | 464 | dev_err(dev, "Internal error\n"); |
456 | } | 465 | } |
@@ -512,7 +521,7 @@ static int sti_pwm_probe_dt(struct sti_pwm_chip *pc) | |||
512 | return PTR_ERR(pc->pwm_cpt_en); | 521 | return PTR_ERR(pc->pwm_cpt_en); |
513 | 522 | ||
514 | pc->pwm_cpt_int_en = devm_regmap_field_alloc(dev, pc->regmap, | 523 | pc->pwm_cpt_int_en = devm_regmap_field_alloc(dev, pc->regmap, |
515 | reg_fields[PWM_CPT_INT_EN]); | 524 | reg_fields[PWM_CPT_INT_EN]); |
516 | if (IS_ERR(pc->pwm_cpt_int_en)) | 525 | if (IS_ERR(pc->pwm_cpt_int_en)) |
517 | return PTR_ERR(pc->pwm_cpt_int_en); | 526 | return PTR_ERR(pc->pwm_cpt_int_en); |
518 | 527 | ||
@@ -575,9 +584,9 @@ static int sti_pwm_probe(struct platform_device *pdev) | |||
575 | * Setup PWM data with default values: some values could be replaced | 584 | * Setup PWM data with default values: some values could be replaced |
576 | * with specific ones provided from Device Tree. | 585 | * with specific ones provided from Device Tree. |
577 | */ | 586 | */ |
578 | cdata->reg_fields = &sti_pwm_regfields[0]; | 587 | cdata->reg_fields = sti_pwm_regfields; |
579 | cdata->max_prescale = 0xff; | 588 | cdata->max_prescale = 0xff; |
580 | cdata->max_pwm_cnt = 255; | 589 | cdata->max_pwm_cnt = 255; |
581 | cdata->pwm_num_devs = 0; | 590 | cdata->pwm_num_devs = 0; |
582 | cdata->cpt_num_devs = 0; | 591 | cdata->cpt_num_devs = 0; |
583 | 592 | ||