aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLee Jones <lee.jones@linaro.org>2016-08-16 05:35:07 -0400
committerThierry Reding <thierry.reding@gmail.com>2016-09-08 04:55:12 -0400
commit7d8a600c916cab347662de212340d3eaf0e93db2 (patch)
treef3c29f24517810af259f03d1dee1e93663179677
parent85a834c42a491deed9ac5bca549b93b7a5455d84 (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.c153
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 */
44enum { 46enum {
@@ -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 */
63enum sti_cpt_edge { 66enum sti_cpt_edge {
64 CPT_EDGE_DISABLED, 67 CPT_EDGE_DISABLED,
@@ -103,13 +106,13 @@ struct sti_pwm_chip {
103}; 106};
104 107
105static const struct reg_field sti_pwm_regfields[MAX_REGFIELDS] = { 108static 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
115static inline struct sti_pwm_chip *to_sti_pwmchip(struct pwm_chip *chip) 118static 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 */
164static int sti_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, 167static 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
280out: 285out:
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