1 // SPDX-License-Identifier: GPL-2.0
2 /*
3 * MediaTek Pulse Width Modulator driver
4 *
5 * Copyright (C) 2015 John Crispin <blogic@openwrt.org>
6 * Copyright (C) 2017 Zhi Mao <zhi.mao@mediatek.com>
7 *
8 */
9
10 #include <linux/err.h>
11 #include <linux/io.h>
12 #include <linux/ioport.h>
13 #include <linux/kernel.h>
14 #include <linux/module.h>
15 #include <linux/clk.h>
16 #include <linux/of.h>
17 #include <linux/platform_device.h>
18 #include <linux/pwm.h>
19 #include <linux/slab.h>
20 #include <linux/types.h>
21
22 /* PWM registers and bits definitions */
23 #define PWMCON 0x00
24 #define PWMHDUR 0x04
25 #define PWMLDUR 0x08
26 #define PWMGDUR 0x0c
27 #define PWMWAVENUM 0x28
28 #define PWMDWIDTH 0x2c
29 #define PWM45DWIDTH_FIXUP 0x30
30 #define PWMTHRES 0x30
31 #define PWM45THRES_FIXUP 0x34
32 #define PWM_CK_26M_SEL_V3 0x74
33 #define PWM_CK_26M_SEL 0x210
34
35 #define PWM_CLK_DIV_MAX 7
36
37 struct pwm_mediatek_of_data {
38 unsigned int num_pwms;
39 bool pwm45_fixup;
40 u16 pwm_ck_26m_sel_reg;
41 const unsigned int *reg_offset;
42 };
43
44 /**
45 * struct pwm_mediatek_chip - struct representing PWM chip
46 * @regs: base address of PWM chip
47 * @clk_top: the top clock generator
48 * @clk_main: the clock used by PWM core
49 * @clk_pwms: the clock used by each PWM channel
50 * @soc: pointer to chip's platform data
51 */
52 struct pwm_mediatek_chip {
53 void __iomem *regs;
54 struct clk *clk_top;
55 struct clk *clk_main;
56 struct clk **clk_pwms;
57 const struct pwm_mediatek_of_data *soc;
58 };
59
60 static const unsigned int mtk_pwm_reg_offset_v1[] = {
61 0x0010, 0x0050, 0x0090, 0x00d0, 0x0110, 0x0150, 0x0190, 0x0220
62 };
63
64 static const unsigned int mtk_pwm_reg_offset_v2[] = {
65 0x0080, 0x00c0, 0x0100, 0x0140, 0x0180, 0x01c0, 0x0200, 0x0240
66 };
67
68 /* PWM IP Version 3.0.2 */
69 static const unsigned int mtk_pwm_reg_offset_v3[] = {
70 0x0100, 0x0200, 0x0300, 0x0400, 0x0500, 0x0600, 0x0700, 0x0800
71 };
72
73 static inline struct pwm_mediatek_chip *
to_pwm_mediatek_chip(struct pwm_chip * chip)74 to_pwm_mediatek_chip(struct pwm_chip *chip)
75 {
76 return pwmchip_get_drvdata(chip);
77 }
78
pwm_mediatek_clk_enable(struct pwm_chip * chip,struct pwm_device * pwm)79 static int pwm_mediatek_clk_enable(struct pwm_chip *chip,
80 struct pwm_device *pwm)
81 {
82 struct pwm_mediatek_chip *pc = to_pwm_mediatek_chip(chip);
83 int ret;
84
85 ret = clk_prepare_enable(pc->clk_top);
86 if (ret < 0)
87 return ret;
88
89 ret = clk_prepare_enable(pc->clk_main);
90 if (ret < 0)
91 goto disable_clk_top;
92
93 ret = clk_prepare_enable(pc->clk_pwms[pwm->hwpwm]);
94 if (ret < 0)
95 goto disable_clk_main;
96
97 return 0;
98
99 disable_clk_main:
100 clk_disable_unprepare(pc->clk_main);
101 disable_clk_top:
102 clk_disable_unprepare(pc->clk_top);
103
104 return ret;
105 }
106
pwm_mediatek_clk_disable(struct pwm_chip * chip,struct pwm_device * pwm)107 static void pwm_mediatek_clk_disable(struct pwm_chip *chip,
108 struct pwm_device *pwm)
109 {
110 struct pwm_mediatek_chip *pc = to_pwm_mediatek_chip(chip);
111
112 clk_disable_unprepare(pc->clk_pwms[pwm->hwpwm]);
113 clk_disable_unprepare(pc->clk_main);
114 clk_disable_unprepare(pc->clk_top);
115 }
116
pwm_mediatek_writel(struct pwm_mediatek_chip * chip,unsigned int num,unsigned int offset,u32 value)117 static inline void pwm_mediatek_writel(struct pwm_mediatek_chip *chip,
118 unsigned int num, unsigned int offset,
119 u32 value)
120 {
121 writel(value, chip->regs + chip->soc->reg_offset[num] + offset);
122 }
123
pwm_mediatek_enable(struct pwm_chip * chip,struct pwm_device * pwm)124 static void pwm_mediatek_enable(struct pwm_chip *chip, struct pwm_device *pwm)
125 {
126 struct pwm_mediatek_chip *pc = to_pwm_mediatek_chip(chip);
127 u32 value;
128
129 value = readl(pc->regs);
130 value |= BIT(pwm->hwpwm);
131 writel(value, pc->regs);
132 }
133
pwm_mediatek_disable(struct pwm_chip * chip,struct pwm_device * pwm)134 static void pwm_mediatek_disable(struct pwm_chip *chip, struct pwm_device *pwm)
135 {
136 struct pwm_mediatek_chip *pc = to_pwm_mediatek_chip(chip);
137 u32 value;
138
139 value = readl(pc->regs);
140 value &= ~BIT(pwm->hwpwm);
141 writel(value, pc->regs);
142 }
143
pwm_mediatek_config(struct pwm_chip * chip,struct pwm_device * pwm,int duty_ns,int period_ns)144 static int pwm_mediatek_config(struct pwm_chip *chip, struct pwm_device *pwm,
145 int duty_ns, int period_ns)
146 {
147 struct pwm_mediatek_chip *pc = to_pwm_mediatek_chip(chip);
148 u32 clkdiv = 0, cnt_period, cnt_duty, reg_width = PWMDWIDTH,
149 reg_thres = PWMTHRES;
150 unsigned long clk_rate;
151 u64 resolution;
152 int ret;
153
154 ret = pwm_mediatek_clk_enable(chip, pwm);
155 if (ret < 0)
156 return ret;
157
158 clk_rate = clk_get_rate(pc->clk_pwms[pwm->hwpwm]);
159 if (!clk_rate) {
160 ret = -EINVAL;
161 goto out;
162 }
163
164 /* Make sure we use the bus clock and not the 26MHz clock */
165 if (pc->soc->pwm_ck_26m_sel_reg)
166 writel(0, pc->regs + pc->soc->pwm_ck_26m_sel_reg);
167
168 /* Using resolution in picosecond gets accuracy higher */
169 resolution = (u64)NSEC_PER_SEC * 1000;
170 do_div(resolution, clk_rate);
171
172 cnt_period = DIV_ROUND_CLOSEST_ULL((u64)period_ns * 1000, resolution);
173 if (!cnt_period)
174 return -EINVAL;
175
176 while (cnt_period > 8192) {
177 resolution *= 2;
178 clkdiv++;
179 cnt_period = DIV_ROUND_CLOSEST_ULL((u64)period_ns * 1000,
180 resolution);
181 }
182
183 if (clkdiv > PWM_CLK_DIV_MAX) {
184 dev_err(pwmchip_parent(chip), "period of %d ns not supported\n", period_ns);
185 ret = -EINVAL;
186 goto out;
187 }
188
189 if (pc->soc->pwm45_fixup && pwm->hwpwm > 2) {
190 /*
191 * PWM[4,5] has distinct offset for PWMDWIDTH and PWMTHRES
192 * from the other PWMs on MT7623.
193 */
194 reg_width = PWM45DWIDTH_FIXUP;
195 reg_thres = PWM45THRES_FIXUP;
196 }
197
198 cnt_duty = DIV_ROUND_CLOSEST_ULL((u64)duty_ns * 1000, resolution);
199
200 pwm_mediatek_writel(pc, pwm->hwpwm, PWMCON, BIT(15) | clkdiv);
201 pwm_mediatek_writel(pc, pwm->hwpwm, reg_width, cnt_period - 1);
202
203 if (cnt_duty) {
204 pwm_mediatek_writel(pc, pwm->hwpwm, reg_thres, cnt_duty - 1);
205 pwm_mediatek_enable(chip, pwm);
206 } else {
207 pwm_mediatek_disable(chip, pwm);
208 }
209
210 out:
211 pwm_mediatek_clk_disable(chip, pwm);
212
213 return ret;
214 }
215
pwm_mediatek_apply(struct pwm_chip * chip,struct pwm_device * pwm,const struct pwm_state * state)216 static int pwm_mediatek_apply(struct pwm_chip *chip, struct pwm_device *pwm,
217 const struct pwm_state *state)
218 {
219 int err;
220
221 if (state->polarity != PWM_POLARITY_NORMAL)
222 return -EINVAL;
223
224 if (!state->enabled) {
225 if (pwm->state.enabled) {
226 pwm_mediatek_disable(chip, pwm);
227 pwm_mediatek_clk_disable(chip, pwm);
228 }
229
230 return 0;
231 }
232
233 err = pwm_mediatek_config(chip, pwm, state->duty_cycle, state->period);
234 if (err)
235 return err;
236
237 if (!pwm->state.enabled)
238 err = pwm_mediatek_clk_enable(chip, pwm);
239
240 return err;
241 }
242
243 static const struct pwm_ops pwm_mediatek_ops = {
244 .apply = pwm_mediatek_apply,
245 };
246
pwm_mediatek_probe(struct platform_device * pdev)247 static int pwm_mediatek_probe(struct platform_device *pdev)
248 {
249 struct pwm_chip *chip;
250 struct pwm_mediatek_chip *pc;
251 const struct pwm_mediatek_of_data *soc;
252 unsigned int i;
253 int ret;
254
255 soc = of_device_get_match_data(&pdev->dev);
256
257 chip = devm_pwmchip_alloc(&pdev->dev, soc->num_pwms, sizeof(*pc));
258 if (IS_ERR(chip))
259 return PTR_ERR(chip);
260 pc = to_pwm_mediatek_chip(chip);
261
262 pc->soc = soc;
263
264 pc->regs = devm_platform_ioremap_resource(pdev, 0);
265 if (IS_ERR(pc->regs))
266 return PTR_ERR(pc->regs);
267
268 pc->clk_pwms = devm_kmalloc_array(&pdev->dev, soc->num_pwms,
269 sizeof(*pc->clk_pwms), GFP_KERNEL);
270 if (!pc->clk_pwms)
271 return -ENOMEM;
272
273 pc->clk_top = devm_clk_get(&pdev->dev, "top");
274 if (IS_ERR(pc->clk_top))
275 return dev_err_probe(&pdev->dev, PTR_ERR(pc->clk_top),
276 "Failed to get top clock\n");
277
278 pc->clk_main = devm_clk_get(&pdev->dev, "main");
279 if (IS_ERR(pc->clk_main))
280 return dev_err_probe(&pdev->dev, PTR_ERR(pc->clk_main),
281 "Failed to get main clock\n");
282
283 for (i = 0; i < soc->num_pwms; i++) {
284 char name[8];
285
286 snprintf(name, sizeof(name), "pwm%d", i + 1);
287
288 pc->clk_pwms[i] = devm_clk_get(&pdev->dev, name);
289 if (IS_ERR(pc->clk_pwms[i]))
290 return dev_err_probe(&pdev->dev, PTR_ERR(pc->clk_pwms[i]),
291 "Failed to get %s clock\n", name);
292 }
293
294 chip->ops = &pwm_mediatek_ops;
295
296 ret = devm_pwmchip_add(&pdev->dev, chip);
297 if (ret < 0)
298 return dev_err_probe(&pdev->dev, ret, "pwmchip_add() failed\n");
299
300 return 0;
301 }
302
303 static const struct pwm_mediatek_of_data mt2712_pwm_data = {
304 .num_pwms = 8,
305 .pwm45_fixup = false,
306 .reg_offset = mtk_pwm_reg_offset_v1,
307 };
308
309 static const struct pwm_mediatek_of_data mt6795_pwm_data = {
310 .num_pwms = 7,
311 .pwm45_fixup = false,
312 .reg_offset = mtk_pwm_reg_offset_v1,
313 };
314
315 static const struct pwm_mediatek_of_data mt7622_pwm_data = {
316 .num_pwms = 6,
317 .pwm45_fixup = false,
318 .pwm_ck_26m_sel_reg = PWM_CK_26M_SEL,
319 .reg_offset = mtk_pwm_reg_offset_v1,
320 };
321
322 static const struct pwm_mediatek_of_data mt7623_pwm_data = {
323 .num_pwms = 5,
324 .pwm45_fixup = true,
325 .reg_offset = mtk_pwm_reg_offset_v1,
326 };
327
328 static const struct pwm_mediatek_of_data mt7628_pwm_data = {
329 .num_pwms = 4,
330 .pwm45_fixup = true,
331 .reg_offset = mtk_pwm_reg_offset_v1,
332 };
333
334 static const struct pwm_mediatek_of_data mt7629_pwm_data = {
335 .num_pwms = 1,
336 .pwm45_fixup = false,
337 .reg_offset = mtk_pwm_reg_offset_v1,
338 };
339
340 static const struct pwm_mediatek_of_data mt7981_pwm_data = {
341 .num_pwms = 3,
342 .pwm45_fixup = false,
343 .pwm_ck_26m_sel_reg = PWM_CK_26M_SEL,
344 .reg_offset = mtk_pwm_reg_offset_v2,
345 };
346
347 static const struct pwm_mediatek_of_data mt7986_pwm_data = {
348 .num_pwms = 2,
349 .pwm45_fixup = false,
350 .pwm_ck_26m_sel_reg = PWM_CK_26M_SEL,
351 .reg_offset = mtk_pwm_reg_offset_v1,
352 };
353
354 static const struct pwm_mediatek_of_data mt7988_pwm_data = {
355 .num_pwms = 8,
356 .pwm45_fixup = false,
357 .reg_offset = mtk_pwm_reg_offset_v2,
358 };
359
360 static const struct pwm_mediatek_of_data mt8183_pwm_data = {
361 .num_pwms = 4,
362 .pwm45_fixup = false,
363 .pwm_ck_26m_sel_reg = PWM_CK_26M_SEL,
364 .reg_offset = mtk_pwm_reg_offset_v1,
365 };
366
367 static const struct pwm_mediatek_of_data mt8365_pwm_data = {
368 .num_pwms = 3,
369 .pwm45_fixup = false,
370 .pwm_ck_26m_sel_reg = PWM_CK_26M_SEL,
371 .reg_offset = mtk_pwm_reg_offset_v1,
372 };
373
374 static const struct pwm_mediatek_of_data mt8516_pwm_data = {
375 .num_pwms = 5,
376 .pwm45_fixup = false,
377 .pwm_ck_26m_sel_reg = PWM_CK_26M_SEL,
378 .reg_offset = mtk_pwm_reg_offset_v1,
379 };
380
381 static const struct pwm_mediatek_of_data mt6991_pwm_data = {
382 .num_pwms = 4,
383 .pwm45_fixup = false,
384 .pwm_ck_26m_sel_reg = PWM_CK_26M_SEL_V3,
385 .reg_offset = mtk_pwm_reg_offset_v3,
386 };
387
388 static const struct of_device_id pwm_mediatek_of_match[] = {
389 { .compatible = "mediatek,mt2712-pwm", .data = &mt2712_pwm_data },
390 { .compatible = "mediatek,mt6795-pwm", .data = &mt6795_pwm_data },
391 { .compatible = "mediatek,mt6991-pwm", .data = &mt6991_pwm_data },
392 { .compatible = "mediatek,mt7622-pwm", .data = &mt7622_pwm_data },
393 { .compatible = "mediatek,mt7623-pwm", .data = &mt7623_pwm_data },
394 { .compatible = "mediatek,mt7628-pwm", .data = &mt7628_pwm_data },
395 { .compatible = "mediatek,mt7629-pwm", .data = &mt7629_pwm_data },
396 { .compatible = "mediatek,mt7981-pwm", .data = &mt7981_pwm_data },
397 { .compatible = "mediatek,mt7986-pwm", .data = &mt7986_pwm_data },
398 { .compatible = "mediatek,mt7988-pwm", .data = &mt7988_pwm_data },
399 { .compatible = "mediatek,mt8183-pwm", .data = &mt8183_pwm_data },
400 { .compatible = "mediatek,mt8365-pwm", .data = &mt8365_pwm_data },
401 { .compatible = "mediatek,mt8516-pwm", .data = &mt8516_pwm_data },
402 { },
403 };
404 MODULE_DEVICE_TABLE(of, pwm_mediatek_of_match);
405
406 static struct platform_driver pwm_mediatek_driver = {
407 .driver = {
408 .name = "pwm-mediatek",
409 .of_match_table = pwm_mediatek_of_match,
410 },
411 .probe = pwm_mediatek_probe,
412 };
413 module_platform_driver(pwm_mediatek_driver);
414
415 MODULE_AUTHOR("John Crispin <blogic@openwrt.org>");
416 MODULE_DESCRIPTION("MediaTek general purpose Pulse Width Modulator driver");
417 MODULE_LICENSE("GPL v2");
418