hc
2023-12-11 d2ccde1c8e90d38cee87a1b0309ad2827f3fd30d
kernel/drivers/pwm/pwm-fsl-ftm.c
....@@ -1,12 +1,8 @@
1
+// SPDX-License-Identifier: GPL-2.0-or-later
12 /*
23 * Freescale FlexTimer Module (FTM) PWM Driver
34 *
45 * Copyright 2012-2013 Freescale Semiconductor, Inc.
5
- *
6
- * This program is free software; you can redistribute it and/or modify
7
- * it under the terms of the GNU General Public License as published by
8
- * the Free Software Foundation; either version 2 of the License, or
9
- * (at your option) any later version.
106 */
117
128 #include <linux/clk.h>
....@@ -22,51 +18,9 @@
2218 #include <linux/pwm.h>
2319 #include <linux/regmap.h>
2420 #include <linux/slab.h>
21
+#include <linux/fsl/ftm.h>
2522
26
-#define FTM_SC 0x00
27
-#define FTM_SC_CLK_MASK_SHIFT 3
28
-#define FTM_SC_CLK_MASK (3 << FTM_SC_CLK_MASK_SHIFT)
2923 #define FTM_SC_CLK(c) (((c) + 1) << FTM_SC_CLK_MASK_SHIFT)
30
-#define FTM_SC_PS_MASK 0x7
31
-
32
-#define FTM_CNT 0x04
33
-#define FTM_MOD 0x08
34
-
35
-#define FTM_CSC_BASE 0x0C
36
-#define FTM_CSC_MSB BIT(5)
37
-#define FTM_CSC_MSA BIT(4)
38
-#define FTM_CSC_ELSB BIT(3)
39
-#define FTM_CSC_ELSA BIT(2)
40
-#define FTM_CSC(_channel) (FTM_CSC_BASE + ((_channel) * 8))
41
-
42
-#define FTM_CV_BASE 0x10
43
-#define FTM_CV(_channel) (FTM_CV_BASE + ((_channel) * 8))
44
-
45
-#define FTM_CNTIN 0x4C
46
-#define FTM_STATUS 0x50
47
-
48
-#define FTM_MODE 0x54
49
-#define FTM_MODE_FTMEN BIT(0)
50
-#define FTM_MODE_INIT BIT(2)
51
-#define FTM_MODE_PWMSYNC BIT(3)
52
-
53
-#define FTM_SYNC 0x58
54
-#define FTM_OUTINIT 0x5C
55
-#define FTM_OUTMASK 0x60
56
-#define FTM_COMBINE 0x64
57
-#define FTM_DEADTIME 0x68
58
-#define FTM_EXTTRIG 0x6C
59
-#define FTM_POL 0x70
60
-#define FTM_FMS 0x74
61
-#define FTM_FILTER 0x78
62
-#define FTM_FLTCTRL 0x7C
63
-#define FTM_QDCTRL 0x80
64
-#define FTM_CONF 0x84
65
-#define FTM_FLTPOL 0x88
66
-#define FTM_SYNCONF 0x8C
67
-#define FTM_INVCTRL 0x90
68
-#define FTM_SWOCTRL 0x94
69
-#define FTM_PWMLOAD 0x98
7024
7125 enum fsl_pwm_clk {
7226 FSL_PWM_CLK_SYS,
....@@ -80,17 +34,19 @@
8034 bool has_enable_bits;
8135 };
8236
37
+struct fsl_pwm_periodcfg {
38
+ enum fsl_pwm_clk clk_select;
39
+ unsigned int clk_ps;
40
+ unsigned int mod_period;
41
+};
42
+
8343 struct fsl_pwm_chip {
8444 struct pwm_chip chip;
85
-
8645 struct mutex lock;
87
-
88
- unsigned int cnt_select;
89
- unsigned int clk_ps;
90
-
9146 struct regmap *regmap;
9247
93
- int period_ns;
48
+ /* This value is valid iff a pwm is running */
49
+ struct fsl_pwm_periodcfg period;
9450
9551 struct clk *ipg_clk;
9652 struct clk *clk[FSL_PWM_CLK_MAX];
....@@ -101,6 +57,33 @@
10157 static inline struct fsl_pwm_chip *to_fsl_chip(struct pwm_chip *chip)
10258 {
10359 return container_of(chip, struct fsl_pwm_chip, chip);
60
+}
61
+
62
+static void ftm_clear_write_protection(struct fsl_pwm_chip *fpc)
63
+{
64
+ u32 val;
65
+
66
+ regmap_read(fpc->regmap, FTM_FMS, &val);
67
+ if (val & FTM_FMS_WPEN)
68
+ regmap_update_bits(fpc->regmap, FTM_MODE, FTM_MODE_WPDIS,
69
+ FTM_MODE_WPDIS);
70
+}
71
+
72
+static void ftm_set_write_protection(struct fsl_pwm_chip *fpc)
73
+{
74
+ regmap_update_bits(fpc->regmap, FTM_FMS, FTM_FMS_WPEN, FTM_FMS_WPEN);
75
+}
76
+
77
+static bool fsl_pwm_periodcfg_are_equal(const struct fsl_pwm_periodcfg *a,
78
+ const struct fsl_pwm_periodcfg *b)
79
+{
80
+ if (a->clk_select != b->clk_select)
81
+ return false;
82
+ if (a->clk_ps != b->clk_ps)
83
+ return false;
84
+ if (a->mod_period != b->mod_period)
85
+ return false;
86
+ return true;
10487 }
10588
10689 static int fsl_pwm_request(struct pwm_chip *chip, struct pwm_device *pwm)
....@@ -133,89 +116,58 @@
133116 clk_disable_unprepare(fpc->ipg_clk);
134117 }
135118
136
-static int fsl_pwm_calculate_default_ps(struct fsl_pwm_chip *fpc,
137
- enum fsl_pwm_clk index)
119
+static unsigned int fsl_pwm_ticks_to_ns(struct fsl_pwm_chip *fpc,
120
+ unsigned int ticks)
138121 {
139
- unsigned long sys_rate, cnt_rate;
140
- unsigned long long ratio;
122
+ unsigned long rate;
123
+ unsigned long long exval;
141124
142
- sys_rate = clk_get_rate(fpc->clk[FSL_PWM_CLK_SYS]);
143
- if (!sys_rate)
144
- return -EINVAL;
145
-
146
- cnt_rate = clk_get_rate(fpc->clk[fpc->cnt_select]);
147
- if (!cnt_rate)
148
- return -EINVAL;
149
-
150
- switch (index) {
151
- case FSL_PWM_CLK_SYS:
152
- fpc->clk_ps = 1;
153
- break;
154
- case FSL_PWM_CLK_FIX:
155
- ratio = 2 * cnt_rate - 1;
156
- do_div(ratio, sys_rate);
157
- fpc->clk_ps = ratio;
158
- break;
159
- case FSL_PWM_CLK_EXT:
160
- ratio = 4 * cnt_rate - 1;
161
- do_div(ratio, sys_rate);
162
- fpc->clk_ps = ratio;
163
- break;
164
- default:
165
- return -EINVAL;
166
- }
167
-
168
- return 0;
125
+ rate = clk_get_rate(fpc->clk[fpc->period.clk_select]);
126
+ exval = ticks;
127
+ exval *= 1000000000UL;
128
+ do_div(exval, rate >> fpc->period.clk_ps);
129
+ return exval;
169130 }
170131
171
-static unsigned long fsl_pwm_calculate_cycles(struct fsl_pwm_chip *fpc,
172
- unsigned long period_ns)
132
+static bool fsl_pwm_calculate_period_clk(struct fsl_pwm_chip *fpc,
133
+ unsigned int period_ns,
134
+ enum fsl_pwm_clk index,
135
+ struct fsl_pwm_periodcfg *periodcfg
136
+ )
173137 {
174
- unsigned long long c, c0;
138
+ unsigned long long c;
139
+ unsigned int ps;
175140
176
- c = clk_get_rate(fpc->clk[fpc->cnt_select]);
141
+ c = clk_get_rate(fpc->clk[index]);
177142 c = c * period_ns;
178143 do_div(c, 1000000000UL);
179144
180
- do {
181
- c0 = c;
182
- do_div(c0, (1 << fpc->clk_ps));
183
- if (c0 <= 0xFFFF)
184
- return (unsigned long)c0;
185
- } while (++fpc->clk_ps < 8);
145
+ if (c == 0)
146
+ return false;
186147
187
- return 0;
188
-}
189
-
190
-static unsigned long fsl_pwm_calculate_period_cycles(struct fsl_pwm_chip *fpc,
191
- unsigned long period_ns,
192
- enum fsl_pwm_clk index)
193
-{
194
- int ret;
195
-
196
- ret = fsl_pwm_calculate_default_ps(fpc, index);
197
- if (ret) {
198
- dev_err(fpc->chip.dev,
199
- "failed to calculate default prescaler: %d\n",
200
- ret);
201
- return 0;
148
+ for (ps = 0; ps < 8 ; ++ps, c >>= 1) {
149
+ if (c <= 0x10000) {
150
+ periodcfg->clk_select = index;
151
+ periodcfg->clk_ps = ps;
152
+ periodcfg->mod_period = c - 1;
153
+ return true;
154
+ }
202155 }
203
-
204
- return fsl_pwm_calculate_cycles(fpc, period_ns);
156
+ return false;
205157 }
206158
207
-static unsigned long fsl_pwm_calculate_period(struct fsl_pwm_chip *fpc,
208
- unsigned long period_ns)
159
+static bool fsl_pwm_calculate_period(struct fsl_pwm_chip *fpc,
160
+ unsigned int period_ns,
161
+ struct fsl_pwm_periodcfg *periodcfg)
209162 {
210163 enum fsl_pwm_clk m0, m1;
211
- unsigned long fix_rate, ext_rate, cycles;
164
+ unsigned long fix_rate, ext_rate;
165
+ bool ret;
212166
213
- cycles = fsl_pwm_calculate_period_cycles(fpc, period_ns,
214
- FSL_PWM_CLK_SYS);
215
- if (cycles) {
216
- fpc->cnt_select = FSL_PWM_CLK_SYS;
217
- return cycles;
218
- }
167
+ ret = fsl_pwm_calculate_period_clk(fpc, period_ns, FSL_PWM_CLK_SYS,
168
+ periodcfg);
169
+ if (ret)
170
+ return true;
219171
220172 fix_rate = clk_get_rate(fpc->clk[FSL_PWM_CLK_FIX]);
221173 ext_rate = clk_get_rate(fpc->clk[FSL_PWM_CLK_EXT]);
....@@ -228,158 +180,181 @@
228180 m1 = FSL_PWM_CLK_FIX;
229181 }
230182
231
- cycles = fsl_pwm_calculate_period_cycles(fpc, period_ns, m0);
232
- if (cycles) {
233
- fpc->cnt_select = m0;
234
- return cycles;
235
- }
183
+ ret = fsl_pwm_calculate_period_clk(fpc, period_ns, m0, periodcfg);
184
+ if (ret)
185
+ return true;
236186
237
- fpc->cnt_select = m1;
238
-
239
- return fsl_pwm_calculate_period_cycles(fpc, period_ns, m1);
187
+ return fsl_pwm_calculate_period_clk(fpc, period_ns, m1, periodcfg);
240188 }
241189
242
-static unsigned long fsl_pwm_calculate_duty(struct fsl_pwm_chip *fpc,
243
- unsigned long period_ns,
244
- unsigned long duty_ns)
190
+static unsigned int fsl_pwm_calculate_duty(struct fsl_pwm_chip *fpc,
191
+ unsigned int duty_ns)
245192 {
246193 unsigned long long duty;
247
- u32 val;
248194
249
- regmap_read(fpc->regmap, FTM_MOD, &val);
250
- duty = (unsigned long long)duty_ns * (val + 1);
195
+ unsigned int period = fpc->period.mod_period + 1;
196
+ unsigned int period_ns = fsl_pwm_ticks_to_ns(fpc, period);
197
+
198
+ duty = (unsigned long long)duty_ns * period;
251199 do_div(duty, period_ns);
252200
253
- return (unsigned long)duty;
201
+ return (unsigned int)duty;
254202 }
255203
256
-static int fsl_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
257
- int duty_ns, int period_ns)
204
+static bool fsl_pwm_is_any_pwm_enabled(struct fsl_pwm_chip *fpc,
205
+ struct pwm_device *pwm)
258206 {
259
- struct fsl_pwm_chip *fpc = to_fsl_chip(chip);
260
- u32 period, duty;
207
+ u32 val;
261208
262
- mutex_lock(&fpc->lock);
209
+ regmap_read(fpc->regmap, FTM_OUTMASK, &val);
210
+ if (~val & 0xFF)
211
+ return true;
212
+ else
213
+ return false;
214
+}
263215
216
+static bool fsl_pwm_is_other_pwm_enabled(struct fsl_pwm_chip *fpc,
217
+ struct pwm_device *pwm)
218
+{
219
+ u32 val;
220
+
221
+ regmap_read(fpc->regmap, FTM_OUTMASK, &val);
222
+ if (~(val | BIT(pwm->hwpwm)) & 0xFF)
223
+ return true;
224
+ else
225
+ return false;
226
+}
227
+
228
+static int fsl_pwm_apply_config(struct fsl_pwm_chip *fpc,
229
+ struct pwm_device *pwm,
230
+ const struct pwm_state *newstate)
231
+{
232
+ unsigned int duty;
233
+ u32 reg_polarity;
234
+
235
+ struct fsl_pwm_periodcfg periodcfg;
236
+ bool do_write_period = false;
237
+
238
+ if (!fsl_pwm_calculate_period(fpc, newstate->period, &periodcfg)) {
239
+ dev_err(fpc->chip.dev, "failed to calculate new period\n");
240
+ return -EINVAL;
241
+ }
242
+
243
+ if (!fsl_pwm_is_any_pwm_enabled(fpc, pwm))
244
+ do_write_period = true;
264245 /*
265246 * The Freescale FTM controller supports only a single period for
266
- * all PWM channels, therefore incompatible changes need to be
267
- * refused.
247
+ * all PWM channels, therefore verify if the newly computed period
248
+ * is different than the current period being used. In such case
249
+ * we allow to change the period only if no other pwm is running.
268250 */
269
- if (fpc->period_ns && fpc->period_ns != period_ns) {
270
- dev_err(fpc->chip.dev,
271
- "conflicting period requested for PWM %u\n",
272
- pwm->hwpwm);
273
- mutex_unlock(&fpc->lock);
274
- return -EBUSY;
275
- }
276
-
277
- if (!fpc->period_ns && duty_ns) {
278
- period = fsl_pwm_calculate_period(fpc, period_ns);
279
- if (!period) {
280
- dev_err(fpc->chip.dev, "failed to calculate period\n");
281
- mutex_unlock(&fpc->lock);
282
- return -EINVAL;
251
+ else if (!fsl_pwm_periodcfg_are_equal(&fpc->period, &periodcfg)) {
252
+ if (fsl_pwm_is_other_pwm_enabled(fpc, pwm)) {
253
+ dev_err(fpc->chip.dev,
254
+ "Cannot change period for PWM %u, disable other PWMs first\n",
255
+ pwm->hwpwm);
256
+ return -EBUSY;
283257 }
258
+ if (fpc->period.clk_select != periodcfg.clk_select) {
259
+ int ret;
260
+ enum fsl_pwm_clk oldclk = fpc->period.clk_select;
261
+ enum fsl_pwm_clk newclk = periodcfg.clk_select;
284262
285
- regmap_update_bits(fpc->regmap, FTM_SC, FTM_SC_PS_MASK,
286
- fpc->clk_ps);
287
- regmap_write(fpc->regmap, FTM_MOD, period - 1);
288
-
289
- fpc->period_ns = period_ns;
263
+ ret = clk_prepare_enable(fpc->clk[newclk]);
264
+ if (ret)
265
+ return ret;
266
+ clk_disable_unprepare(fpc->clk[oldclk]);
267
+ }
268
+ do_write_period = true;
290269 }
291270
292
- mutex_unlock(&fpc->lock);
271
+ ftm_clear_write_protection(fpc);
293272
294
- duty = fsl_pwm_calculate_duty(fpc, period_ns, duty_ns);
273
+ if (do_write_period) {
274
+ regmap_update_bits(fpc->regmap, FTM_SC, FTM_SC_CLK_MASK,
275
+ FTM_SC_CLK(periodcfg.clk_select));
276
+ regmap_update_bits(fpc->regmap, FTM_SC, FTM_SC_PS_MASK,
277
+ periodcfg.clk_ps);
278
+ regmap_write(fpc->regmap, FTM_MOD, periodcfg.mod_period);
279
+
280
+ fpc->period = periodcfg;
281
+ }
282
+
283
+ duty = fsl_pwm_calculate_duty(fpc, newstate->duty_cycle);
295284
296285 regmap_write(fpc->regmap, FTM_CSC(pwm->hwpwm),
297286 FTM_CSC_MSB | FTM_CSC_ELSB);
298287 regmap_write(fpc->regmap, FTM_CV(pwm->hwpwm), duty);
299288
289
+ reg_polarity = 0;
290
+ if (newstate->polarity == PWM_POLARITY_INVERSED)
291
+ reg_polarity = BIT(pwm->hwpwm);
292
+
293
+ regmap_update_bits(fpc->regmap, FTM_POL, BIT(pwm->hwpwm), reg_polarity);
294
+
295
+ ftm_set_write_protection(fpc);
296
+
300297 return 0;
301298 }
302299
303
-static int fsl_pwm_set_polarity(struct pwm_chip *chip,
304
- struct pwm_device *pwm,
305
- enum pwm_polarity polarity)
300
+static int fsl_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
301
+ const struct pwm_state *newstate)
306302 {
307303 struct fsl_pwm_chip *fpc = to_fsl_chip(chip);
308
- u32 val;
304
+ struct pwm_state *oldstate = &pwm->state;
305
+ int ret = 0;
309306
310
- regmap_read(fpc->regmap, FTM_POL, &val);
307
+ /*
308
+ * oldstate to newstate : action
309
+ *
310
+ * disabled to disabled : ignore
311
+ * enabled to disabled : disable
312
+ * enabled to enabled : update settings
313
+ * disabled to enabled : update settings + enable
314
+ */
311315
312
- if (polarity == PWM_POLARITY_INVERSED)
313
- val |= BIT(pwm->hwpwm);
314
- else
315
- val &= ~BIT(pwm->hwpwm);
316
+ mutex_lock(&fpc->lock);
316317
317
- regmap_write(fpc->regmap, FTM_POL, val);
318
+ if (!newstate->enabled) {
319
+ if (oldstate->enabled) {
320
+ regmap_update_bits(fpc->regmap, FTM_OUTMASK,
321
+ BIT(pwm->hwpwm), BIT(pwm->hwpwm));
322
+ clk_disable_unprepare(fpc->clk[FSL_PWM_CLK_CNTEN]);
323
+ clk_disable_unprepare(fpc->clk[fpc->period.clk_select]);
324
+ }
318325
319
- return 0;
320
-}
321
-
322
-static int fsl_counter_clock_enable(struct fsl_pwm_chip *fpc)
323
-{
324
- int ret;
325
-
326
- /* select counter clock source */
327
- regmap_update_bits(fpc->regmap, FTM_SC, FTM_SC_CLK_MASK,
328
- FTM_SC_CLK(fpc->cnt_select));
329
-
330
- ret = clk_prepare_enable(fpc->clk[fpc->cnt_select]);
331
- if (ret)
332
- return ret;
333
-
334
- ret = clk_prepare_enable(fpc->clk[FSL_PWM_CLK_CNTEN]);
335
- if (ret) {
336
- clk_disable_unprepare(fpc->clk[fpc->cnt_select]);
337
- return ret;
326
+ goto end_mutex;
338327 }
339328
340
- return 0;
341
-}
329
+ ret = fsl_pwm_apply_config(fpc, pwm, newstate);
330
+ if (ret)
331
+ goto end_mutex;
342332
343
-static int fsl_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm)
344
-{
345
- struct fsl_pwm_chip *fpc = to_fsl_chip(chip);
346
- int ret;
333
+ /* check if need to enable */
334
+ if (!oldstate->enabled) {
335
+ ret = clk_prepare_enable(fpc->clk[fpc->period.clk_select]);
336
+ if (ret)
337
+ goto end_mutex;
347338
348
- mutex_lock(&fpc->lock);
349
- regmap_update_bits(fpc->regmap, FTM_OUTMASK, BIT(pwm->hwpwm), 0);
339
+ ret = clk_prepare_enable(fpc->clk[FSL_PWM_CLK_CNTEN]);
340
+ if (ret) {
341
+ clk_disable_unprepare(fpc->clk[fpc->period.clk_select]);
342
+ goto end_mutex;
343
+ }
350344
351
- ret = fsl_counter_clock_enable(fpc);
345
+ regmap_update_bits(fpc->regmap, FTM_OUTMASK, BIT(pwm->hwpwm),
346
+ 0);
347
+ }
348
+
349
+end_mutex:
352350 mutex_unlock(&fpc->lock);
353
-
354351 return ret;
355
-}
356
-
357
-static void fsl_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm)
358
-{
359
- struct fsl_pwm_chip *fpc = to_fsl_chip(chip);
360
- u32 val;
361
-
362
- mutex_lock(&fpc->lock);
363
- regmap_update_bits(fpc->regmap, FTM_OUTMASK, BIT(pwm->hwpwm),
364
- BIT(pwm->hwpwm));
365
-
366
- clk_disable_unprepare(fpc->clk[FSL_PWM_CLK_CNTEN]);
367
- clk_disable_unprepare(fpc->clk[fpc->cnt_select]);
368
-
369
- regmap_read(fpc->regmap, FTM_OUTMASK, &val);
370
- if ((val & 0xFF) == 0xFF)
371
- fpc->period_ns = 0;
372
-
373
- mutex_unlock(&fpc->lock);
374352 }
375353
376354 static const struct pwm_ops fsl_pwm_ops = {
377355 .request = fsl_pwm_request,
378356 .free = fsl_pwm_free,
379
- .config = fsl_pwm_config,
380
- .set_polarity = fsl_pwm_set_polarity,
381
- .enable = fsl_pwm_enable,
382
- .disable = fsl_pwm_disable,
357
+ .apply = fsl_pwm_apply,
383358 .owner = THIS_MODULE,
384359 };
385360
....@@ -403,6 +378,8 @@
403378 static bool fsl_pwm_volatile_reg(struct device *dev, unsigned int reg)
404379 {
405380 switch (reg) {
381
+ case FTM_FMS:
382
+ case FTM_MODE:
406383 case FTM_CNT:
407384 return true;
408385 }
....@@ -520,7 +497,7 @@
520497 continue;
521498
522499 clk_disable_unprepare(fpc->clk[FSL_PWM_CLK_CNTEN]);
523
- clk_disable_unprepare(fpc->clk[fpc->cnt_select]);
500
+ clk_disable_unprepare(fpc->clk[fpc->period.clk_select]);
524501 }
525502
526503 return 0;
....@@ -542,7 +519,7 @@
542519 if (!pwm_is_enabled(pwm))
543520 continue;
544521
545
- clk_prepare_enable(fpc->clk[fpc->cnt_select]);
522
+ clk_prepare_enable(fpc->clk[fpc->period.clk_select]);
546523 clk_prepare_enable(fpc->clk[FSL_PWM_CLK_CNTEN]);
547524 }
548525