diff options
Diffstat (limited to 'drivers/pwm/pwm-stm32.c')
-rw-r--r-- | drivers/pwm/pwm-stm32.c | 257 |
1 files changed, 257 insertions, 0 deletions
diff --git a/drivers/pwm/pwm-stm32.c b/drivers/pwm/pwm-stm32.c index 2708212933f7..09383c6720fb 100644 --- a/drivers/pwm/pwm-stm32.c +++ b/drivers/pwm/pwm-stm32.c | |||
@@ -8,6 +8,7 @@ | |||
8 | * pwm-atmel.c from Bo Shen | 8 | * pwm-atmel.c from Bo Shen |
9 | */ | 9 | */ |
10 | 10 | ||
11 | #include <linux/bitfield.h> | ||
11 | #include <linux/mfd/stm32-timers.h> | 12 | #include <linux/mfd/stm32-timers.h> |
12 | #include <linux/module.h> | 13 | #include <linux/module.h> |
13 | #include <linux/of.h> | 14 | #include <linux/of.h> |
@@ -25,6 +26,7 @@ struct stm32_pwm { | |||
25 | struct regmap *regmap; | 26 | struct regmap *regmap; |
26 | u32 max_arr; | 27 | u32 max_arr; |
27 | bool have_complementary_output; | 28 | bool have_complementary_output; |
29 | u32 capture[4] ____cacheline_aligned; /* DMA'able buffer */ | ||
28 | }; | 30 | }; |
29 | 31 | ||
30 | struct stm32_breakinput { | 32 | struct stm32_breakinput { |
@@ -62,6 +64,258 @@ static int write_ccrx(struct stm32_pwm *dev, int ch, u32 value) | |||
62 | return -EINVAL; | 64 | return -EINVAL; |
63 | } | 65 | } |
64 | 66 | ||
67 | #define TIM_CCER_CC12P (TIM_CCER_CC1P | TIM_CCER_CC2P) | ||
68 | #define TIM_CCER_CC12E (TIM_CCER_CC1E | TIM_CCER_CC2E) | ||
69 | #define TIM_CCER_CC34P (TIM_CCER_CC3P | TIM_CCER_CC4P) | ||
70 | #define TIM_CCER_CC34E (TIM_CCER_CC3E | TIM_CCER_CC4E) | ||
71 | |||
72 | /* | ||
73 | * Capture using PWM input mode: | ||
74 | * ___ ___ | ||
75 | * TI[1, 2, 3 or 4]: ........._| |________| | ||
76 | * ^0 ^1 ^2 | ||
77 | * . . . | ||
78 | * . . XXXXX | ||
79 | * . . XXXXX | | ||
80 | * . XXXXX . | | ||
81 | * XXXXX . . | | ||
82 | * COUNTER: ______XXXXX . . . |_XXX | ||
83 | * start^ . . . ^stop | ||
84 | * . . . . | ||
85 | * v v . v | ||
86 | * v | ||
87 | * CCR1/CCR3: tx..........t0...........t2 | ||
88 | * CCR2/CCR4: tx..............t1......... | ||
89 | * | ||
90 | * DMA burst transfer: | | | ||
91 | * v v | ||
92 | * DMA buffer: { t0, tx } { t2, t1 } | ||
93 | * DMA done: ^ | ||
94 | * | ||
95 | * 0: IC1/3 snapchot on rising edge: counter value -> CCR1/CCR3 | ||
96 | * + DMA transfer CCR[1/3] & CCR[2/4] values (t0, tx: doesn't care) | ||
97 | * 1: IC2/4 snapchot on falling edge: counter value -> CCR2/CCR4 | ||
98 | * 2: IC1/3 snapchot on rising edge: counter value -> CCR1/CCR3 | ||
99 | * + DMA transfer CCR[1/3] & CCR[2/4] values (t2, t1) | ||
100 | * | ||
101 | * DMA done, compute: | ||
102 | * - Period = t2 - t0 | ||
103 | * - Duty cycle = t1 - t0 | ||
104 | */ | ||
105 | static int stm32_pwm_raw_capture(struct stm32_pwm *priv, struct pwm_device *pwm, | ||
106 | unsigned long tmo_ms, u32 *raw_prd, | ||
107 | u32 *raw_dty) | ||
108 | { | ||
109 | struct device *parent = priv->chip.dev->parent; | ||
110 | enum stm32_timers_dmas dma_id; | ||
111 | u32 ccen, ccr; | ||
112 | int ret; | ||
113 | |||
114 | /* Ensure registers have been updated, enable counter and capture */ | ||
115 | regmap_update_bits(priv->regmap, TIM_EGR, TIM_EGR_UG, TIM_EGR_UG); | ||
116 | regmap_update_bits(priv->regmap, TIM_CR1, TIM_CR1_CEN, TIM_CR1_CEN); | ||
117 | |||
118 | /* Use cc1 or cc3 DMA resp for PWM input channels 1 & 2 or 3 & 4 */ | ||
119 | dma_id = pwm->hwpwm < 2 ? STM32_TIMERS_DMA_CH1 : STM32_TIMERS_DMA_CH3; | ||
120 | ccen = pwm->hwpwm < 2 ? TIM_CCER_CC12E : TIM_CCER_CC34E; | ||
121 | ccr = pwm->hwpwm < 2 ? TIM_CCR1 : TIM_CCR3; | ||
122 | regmap_update_bits(priv->regmap, TIM_CCER, ccen, ccen); | ||
123 | |||
124 | /* | ||
125 | * Timer DMA burst mode. Request 2 registers, 2 bursts, to get both | ||
126 | * CCR1 & CCR2 (or CCR3 & CCR4) on each capture event. | ||
127 | * We'll get two capture snapchots: { CCR1, CCR2 }, { CCR1, CCR2 } | ||
128 | * or { CCR3, CCR4 }, { CCR3, CCR4 } | ||
129 | */ | ||
130 | ret = stm32_timers_dma_burst_read(parent, priv->capture, dma_id, ccr, 2, | ||
131 | 2, tmo_ms); | ||
132 | if (ret) | ||
133 | goto stop; | ||
134 | |||
135 | /* Period: t2 - t0 (take care of counter overflow) */ | ||
136 | if (priv->capture[0] <= priv->capture[2]) | ||
137 | *raw_prd = priv->capture[2] - priv->capture[0]; | ||
138 | else | ||
139 | *raw_prd = priv->max_arr - priv->capture[0] + priv->capture[2]; | ||
140 | |||
141 | /* Duty cycle capture requires at least two capture units */ | ||
142 | if (pwm->chip->npwm < 2) | ||
143 | *raw_dty = 0; | ||
144 | else if (priv->capture[0] <= priv->capture[3]) | ||
145 | *raw_dty = priv->capture[3] - priv->capture[0]; | ||
146 | else | ||
147 | *raw_dty = priv->max_arr - priv->capture[0] + priv->capture[3]; | ||
148 | |||
149 | if (*raw_dty > *raw_prd) { | ||
150 | /* | ||
151 | * Race beetween PWM input and DMA: it may happen | ||
152 | * falling edge triggers new capture on TI2/4 before DMA | ||
153 | * had a chance to read CCR2/4. It means capture[1] | ||
154 | * contains period + duty_cycle. So, subtract period. | ||
155 | */ | ||
156 | *raw_dty -= *raw_prd; | ||
157 | } | ||
158 | |||
159 | stop: | ||
160 | regmap_update_bits(priv->regmap, TIM_CCER, ccen, 0); | ||
161 | regmap_update_bits(priv->regmap, TIM_CR1, TIM_CR1_CEN, 0); | ||
162 | |||
163 | return ret; | ||
164 | } | ||
165 | |||
166 | static int stm32_pwm_capture(struct pwm_chip *chip, struct pwm_device *pwm, | ||
167 | struct pwm_capture *result, unsigned long tmo_ms) | ||
168 | { | ||
169 | struct stm32_pwm *priv = to_stm32_pwm_dev(chip); | ||
170 | unsigned long long prd, div, dty; | ||
171 | unsigned long rate; | ||
172 | unsigned int psc = 0, icpsc, scale; | ||
173 | u32 raw_prd = 0, raw_dty = 0; | ||
174 | int ret = 0; | ||
175 | |||
176 | mutex_lock(&priv->lock); | ||
177 | |||
178 | if (active_channels(priv)) { | ||
179 | ret = -EBUSY; | ||
180 | goto unlock; | ||
181 | } | ||
182 | |||
183 | ret = clk_enable(priv->clk); | ||
184 | if (ret) { | ||
185 | dev_err(priv->chip.dev, "failed to enable counter clock\n"); | ||
186 | goto unlock; | ||
187 | } | ||
188 | |||
189 | rate = clk_get_rate(priv->clk); | ||
190 | if (!rate) { | ||
191 | ret = -EINVAL; | ||
192 | goto clk_dis; | ||
193 | } | ||
194 | |||
195 | /* prescaler: fit timeout window provided by upper layer */ | ||
196 | div = (unsigned long long)rate * (unsigned long long)tmo_ms; | ||
197 | do_div(div, MSEC_PER_SEC); | ||
198 | prd = div; | ||
199 | while ((div > priv->max_arr) && (psc < MAX_TIM_PSC)) { | ||
200 | psc++; | ||
201 | div = prd; | ||
202 | do_div(div, psc + 1); | ||
203 | } | ||
204 | regmap_write(priv->regmap, TIM_ARR, priv->max_arr); | ||
205 | regmap_write(priv->regmap, TIM_PSC, psc); | ||
206 | |||
207 | /* Map TI1 or TI2 PWM input to IC1 & IC2 (or TI3/4 to IC3 & IC4) */ | ||
208 | regmap_update_bits(priv->regmap, | ||
209 | pwm->hwpwm < 2 ? TIM_CCMR1 : TIM_CCMR2, | ||
210 | TIM_CCMR_CC1S | TIM_CCMR_CC2S, pwm->hwpwm & 0x1 ? | ||
211 | TIM_CCMR_CC1S_TI2 | TIM_CCMR_CC2S_TI2 : | ||
212 | TIM_CCMR_CC1S_TI1 | TIM_CCMR_CC2S_TI1); | ||
213 | |||
214 | /* Capture period on IC1/3 rising edge, duty cycle on IC2/4 falling. */ | ||
215 | regmap_update_bits(priv->regmap, TIM_CCER, pwm->hwpwm < 2 ? | ||
216 | TIM_CCER_CC12P : TIM_CCER_CC34P, pwm->hwpwm < 2 ? | ||
217 | TIM_CCER_CC2P : TIM_CCER_CC4P); | ||
218 | |||
219 | ret = stm32_pwm_raw_capture(priv, pwm, tmo_ms, &raw_prd, &raw_dty); | ||
220 | if (ret) | ||
221 | goto stop; | ||
222 | |||
223 | /* | ||
224 | * Got a capture. Try to improve accuracy at high rates: | ||
225 | * - decrease counter clock prescaler, scale up to max rate. | ||
226 | * - use input prescaler, capture once every /2 /4 or /8 edges. | ||
227 | */ | ||
228 | if (raw_prd) { | ||
229 | u32 max_arr = priv->max_arr - 0x1000; /* arbitrary margin */ | ||
230 | |||
231 | scale = max_arr / min(max_arr, raw_prd); | ||
232 | } else { | ||
233 | scale = priv->max_arr; /* bellow resolution, use max scale */ | ||
234 | } | ||
235 | |||
236 | if (psc && scale > 1) { | ||
237 | /* 2nd measure with new scale */ | ||
238 | psc /= scale; | ||
239 | regmap_write(priv->regmap, TIM_PSC, psc); | ||
240 | ret = stm32_pwm_raw_capture(priv, pwm, tmo_ms, &raw_prd, | ||
241 | &raw_dty); | ||
242 | if (ret) | ||
243 | goto stop; | ||
244 | } | ||
245 | |||
246 | /* Compute intermediate period not to exceed timeout at low rates */ | ||
247 | prd = (unsigned long long)raw_prd * (psc + 1) * NSEC_PER_SEC; | ||
248 | do_div(prd, rate); | ||
249 | |||
250 | for (icpsc = 0; icpsc < MAX_TIM_ICPSC ; icpsc++) { | ||
251 | /* input prescaler: also keep arbitrary margin */ | ||
252 | if (raw_prd >= (priv->max_arr - 0x1000) >> (icpsc + 1)) | ||
253 | break; | ||
254 | if (prd >= (tmo_ms * NSEC_PER_MSEC) >> (icpsc + 2)) | ||
255 | break; | ||
256 | } | ||
257 | |||
258 | if (!icpsc) | ||
259 | goto done; | ||
260 | |||
261 | /* Last chance to improve period accuracy, using input prescaler */ | ||
262 | regmap_update_bits(priv->regmap, | ||
263 | pwm->hwpwm < 2 ? TIM_CCMR1 : TIM_CCMR2, | ||
264 | TIM_CCMR_IC1PSC | TIM_CCMR_IC2PSC, | ||
265 | FIELD_PREP(TIM_CCMR_IC1PSC, icpsc) | | ||
266 | FIELD_PREP(TIM_CCMR_IC2PSC, icpsc)); | ||
267 | |||
268 | ret = stm32_pwm_raw_capture(priv, pwm, tmo_ms, &raw_prd, &raw_dty); | ||
269 | if (ret) | ||
270 | goto stop; | ||
271 | |||
272 | if (raw_dty >= (raw_prd >> icpsc)) { | ||
273 | /* | ||
274 | * We may fall here using input prescaler, when input | ||
275 | * capture starts on high side (before falling edge). | ||
276 | * Example with icpsc to capture on each 4 events: | ||
277 | * | ||
278 | * start 1st capture 2nd capture | ||
279 | * v v v | ||
280 | * ___ _____ _____ _____ _____ ____ | ||
281 | * TI1..4 |__| |__| |__| |__| |__| | ||
282 | * v v . . . . . v v | ||
283 | * icpsc1/3: . 0 . 1 . 2 . 3 . 0 | ||
284 | * icpsc2/4: 0 1 2 3 0 | ||
285 | * v v v v | ||
286 | * CCR1/3 ......t0..............................t2 | ||
287 | * CCR2/4 ..t1..............................t1'... | ||
288 | * . . . | ||
289 | * Capture0: .<----------------------------->. | ||
290 | * Capture1: .<-------------------------->. . | ||
291 | * . . . | ||
292 | * Period: .<------> . . | ||
293 | * Low side: .<>. | ||
294 | * | ||
295 | * Result: | ||
296 | * - Period = Capture0 / icpsc | ||
297 | * - Duty = Period - Low side = Period - (Capture0 - Capture1) | ||
298 | */ | ||
299 | raw_dty = (raw_prd >> icpsc) - (raw_prd - raw_dty); | ||
300 | } | ||
301 | |||
302 | done: | ||
303 | prd = (unsigned long long)raw_prd * (psc + 1) * NSEC_PER_SEC; | ||
304 | result->period = DIV_ROUND_UP_ULL(prd, rate << icpsc); | ||
305 | dty = (unsigned long long)raw_dty * (psc + 1) * NSEC_PER_SEC; | ||
306 | result->duty_cycle = DIV_ROUND_UP_ULL(dty, rate); | ||
307 | stop: | ||
308 | regmap_write(priv->regmap, TIM_CCER, 0); | ||
309 | regmap_write(priv->regmap, pwm->hwpwm < 2 ? TIM_CCMR1 : TIM_CCMR2, 0); | ||
310 | regmap_write(priv->regmap, TIM_PSC, 0); | ||
311 | clk_dis: | ||
312 | clk_disable(priv->clk); | ||
313 | unlock: | ||
314 | mutex_unlock(&priv->lock); | ||
315 | |||
316 | return ret; | ||
317 | } | ||
318 | |||
65 | static int stm32_pwm_config(struct stm32_pwm *priv, int ch, | 319 | static int stm32_pwm_config(struct stm32_pwm *priv, int ch, |
66 | int duty_ns, int period_ns) | 320 | int duty_ns, int period_ns) |
67 | { | 321 | { |
@@ -230,6 +484,9 @@ static int stm32_pwm_apply_locked(struct pwm_chip *chip, struct pwm_device *pwm, | |||
230 | static const struct pwm_ops stm32pwm_ops = { | 484 | static const struct pwm_ops stm32pwm_ops = { |
231 | .owner = THIS_MODULE, | 485 | .owner = THIS_MODULE, |
232 | .apply = stm32_pwm_apply_locked, | 486 | .apply = stm32_pwm_apply_locked, |
487 | #if IS_ENABLED(CONFIG_DMA_ENGINE) | ||
488 | .capture = stm32_pwm_capture, | ||
489 | #endif | ||
233 | }; | 490 | }; |
234 | 491 | ||
235 | static int stm32_pwm_set_breakinput(struct stm32_pwm *priv, | 492 | static int stm32_pwm_set_breakinput(struct stm32_pwm *priv, |