xref: /linux/drivers/pwm/pwm-mediatek.c (revision d30c1683aaecb93d2ab95685dc4300a33d3cea7a)
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/bitfield.h>
11 #include <linux/err.h>
12 #include <linux/io.h>
13 #include <linux/ioport.h>
14 #include <linux/kernel.h>
15 #include <linux/module.h>
16 #include <linux/clk.h>
17 #include <linux/of.h>
18 #include <linux/platform_device.h>
19 #include <linux/pwm.h>
20 #include <linux/slab.h>
21 #include <linux/types.h>
22 
23 /* PWM registers and bits definitions */
24 #define PWMCON			0x00
25 #define PWMCON_CLKDIV			GENMASK(2, 0)
26 #define PWMHDUR			0x04
27 #define PWMLDUR			0x08
28 #define PWMGDUR			0x0c
29 #define PWMWAVENUM		0x28
30 #define PWMDWIDTH		0x2c
31 #define PWMDWIDTH_PERIOD		GENMASK(12, 0)
32 #define PWM45DWIDTH_FIXUP	0x30
33 #define PWMTHRES		0x30
34 #define PWMTHRES_DUTY			GENMASK(12, 0)
35 #define PWM45THRES_FIXUP	0x34
36 #define PWM_CK_26M_SEL_V3	0x74
37 #define PWM_CK_26M_SEL		0x210
38 
39 struct pwm_mediatek_of_data {
40 	unsigned int num_pwms;
41 	bool pwm45_fixup;
42 	u16 pwm_ck_26m_sel_reg;
43 	unsigned int chanreg_base;
44 	unsigned int chanreg_width;
45 };
46 
47 /**
48  * struct pwm_mediatek_chip - struct representing PWM chip
49  * @regs: base address of PWM chip
50  * @clk_top: the top clock generator
51  * @clk_main: the clock used by PWM core
52  * @soc: pointer to chip's platform data
53  * @clk_pwms: the clock and clkrate used by each PWM channel
54  */
55 struct pwm_mediatek_chip {
56 	void __iomem *regs;
57 	struct clk *clk_top;
58 	struct clk *clk_main;
59 	const struct pwm_mediatek_of_data *soc;
60 	struct {
61 		struct clk *clk;
62 		unsigned long rate;
63 	} clk_pwms[];
64 };
65 
66 static inline struct pwm_mediatek_chip *
67 to_pwm_mediatek_chip(struct pwm_chip *chip)
68 {
69 	return pwmchip_get_drvdata(chip);
70 }
71 
72 static int pwm_mediatek_clk_enable(struct pwm_mediatek_chip *pc,
73 				   unsigned int hwpwm)
74 {
75 	int ret;
76 
77 	ret = clk_prepare_enable(pc->clk_top);
78 	if (ret < 0)
79 		return ret;
80 
81 	ret = clk_prepare_enable(pc->clk_main);
82 	if (ret < 0)
83 		goto disable_clk_top;
84 
85 	ret = clk_prepare_enable(pc->clk_pwms[hwpwm].clk);
86 	if (ret < 0)
87 		goto disable_clk_main;
88 
89 	if (!pc->clk_pwms[hwpwm].rate) {
90 		pc->clk_pwms[hwpwm].rate = clk_get_rate(pc->clk_pwms[hwpwm].clk);
91 
92 		/*
93 		 * With the clk running with not more than 1 GHz the
94 		 * calculations in .apply() won't overflow.
95 		 */
96 		if (!pc->clk_pwms[hwpwm].rate ||
97 		    pc->clk_pwms[hwpwm].rate > 1000000000) {
98 			ret = -EINVAL;
99 			goto disable_clk_hwpwm;
100 		}
101 	}
102 
103 	return 0;
104 
105 disable_clk_hwpwm:
106 	clk_disable_unprepare(pc->clk_pwms[hwpwm].clk);
107 disable_clk_main:
108 	clk_disable_unprepare(pc->clk_main);
109 disable_clk_top:
110 	clk_disable_unprepare(pc->clk_top);
111 
112 	return ret;
113 }
114 
115 static void pwm_mediatek_clk_disable(struct pwm_mediatek_chip *pc,
116 				     unsigned int hwpwm)
117 {
118 	clk_disable_unprepare(pc->clk_pwms[hwpwm].clk);
119 	clk_disable_unprepare(pc->clk_main);
120 	clk_disable_unprepare(pc->clk_top);
121 }
122 
123 static inline void pwm_mediatek_writel(struct pwm_mediatek_chip *chip,
124 				       unsigned int num, unsigned int offset,
125 				       u32 value)
126 {
127 	writel(value, chip->regs + chip->soc->chanreg_base +
128 	       num * chip->soc->chanreg_width + offset);
129 }
130 
131 static inline u32 pwm_mediatek_readl(struct pwm_mediatek_chip *chip,
132 				     unsigned int num, unsigned int offset)
133 {
134 	return readl(chip->regs + chip->soc->chanreg_base +
135 		     num * chip->soc->chanreg_width + offset);
136 }
137 
138 struct pwm_mediatek_waveform {
139 	u32 enable;
140 	u32 con;
141 	u32 width;
142 	u32 thres;
143 };
144 
145 static int pwm_mediatek_round_waveform_tohw(struct pwm_chip *chip, struct pwm_device *pwm,
146 					    const struct pwm_waveform *wf, void *_wfhw)
147 {
148 	struct pwm_mediatek_waveform *wfhw = _wfhw;
149 	struct pwm_mediatek_chip *pc = to_pwm_mediatek_chip(chip);
150 	u32 clkdiv, enable;
151 	u64 cnt_period, cnt_duty;
152 	unsigned long clk_rate;
153 	int ret = 0;
154 
155 	if (wf->period_length_ns == 0) {
156 		*wfhw = (typeof(*wfhw)){
157 			.enable = 0,
158 		};
159 
160 		return 0;
161 	}
162 
163 	if (!pc->clk_pwms[pwm->hwpwm].rate) {
164 		struct clk *clk = pc->clk_pwms[pwm->hwpwm].clk;
165 
166 		ret = clk_prepare_enable(clk);
167 		if (ret)
168 			return ret;
169 
170 		pc->clk_pwms[pwm->hwpwm].rate = clk_get_rate(clk);
171 
172 		clk_disable_unprepare(clk);
173 	}
174 
175 	clk_rate = pc->clk_pwms[pwm->hwpwm].rate;
176 	if (clk_rate == 0 || clk_rate > 1000000000)
177 		return -EINVAL;
178 
179 	cnt_period = mul_u64_u64_div_u64(wf->period_length_ns, clk_rate, NSEC_PER_SEC);
180 	if (cnt_period == 0) {
181 		cnt_period = 1;
182 		ret = 1;
183 	}
184 
185 	if (cnt_period > FIELD_MAX(PWMDWIDTH_PERIOD) + 1) {
186 		if (cnt_period >= ((FIELD_MAX(PWMDWIDTH_PERIOD) + 1) << FIELD_MAX(PWMCON_CLKDIV))) {
187 			clkdiv = FIELD_MAX(PWMCON_CLKDIV);
188 			cnt_period = FIELD_MAX(PWMDWIDTH_PERIOD) + 1;
189 		} else {
190 			clkdiv = ilog2(cnt_period) - ilog2(FIELD_MAX(PWMDWIDTH_PERIOD));
191 			cnt_period >>= clkdiv;
192 		}
193 	} else {
194 		clkdiv = 0;
195 	}
196 
197 	cnt_duty = mul_u64_u64_div_u64(wf->duty_length_ns, clk_rate, NSEC_PER_SEC) >> clkdiv;
198 	if (cnt_duty > cnt_period)
199 		cnt_duty = cnt_period;
200 
201 	if (cnt_duty) {
202 		cnt_duty -= 1;
203 		enable = BIT(pwm->hwpwm);
204 	} else {
205 		enable = 0;
206 	}
207 
208 	cnt_period -= 1;
209 
210 	dev_dbg(&chip->dev, "pwm#%u: %lld/%lld @%lu -> ENABLE: %x, CON: %x, PERIOD: %llx, DUTY: %llx\n",
211 		pwm->hwpwm, wf->duty_length_ns, wf->period_length_ns, clk_rate,
212 		enable, clkdiv, cnt_period, cnt_duty);
213 
214 	*wfhw = (typeof(*wfhw)){
215 		.enable = enable,
216 		.con = clkdiv,
217 		.width = cnt_period,
218 		.thres = cnt_duty,
219 	};
220 
221 	return ret;
222 }
223 
224 static int pwm_mediatek_round_waveform_fromhw(struct pwm_chip *chip, struct pwm_device *pwm,
225 					      const void *_wfhw, struct pwm_waveform *wf)
226 {
227 	const struct pwm_mediatek_waveform *wfhw = _wfhw;
228 	struct pwm_mediatek_chip *pc = to_pwm_mediatek_chip(chip);
229 	u32 clkdiv, cnt_period, cnt_duty;
230 	unsigned long clk_rate;
231 
232 	/*
233 	 * When _wfhw was populated, the clock was on, so .rate is
234 	 * already set appropriately.
235 	 */
236 	clk_rate = pc->clk_pwms[pwm->hwpwm].rate;
237 
238 	if (wfhw->enable) {
239 		clkdiv = FIELD_GET(PWMCON_CLKDIV, wfhw->con);
240 		cnt_period = FIELD_GET(PWMDWIDTH_PERIOD, wfhw->width);
241 		cnt_duty = FIELD_GET(PWMTHRES_DUTY, wfhw->thres);
242 
243 		/*
244 		 * cnt_period is a 13 bit value, NSEC_PER_SEC is 30 bits wide
245 		 * and clkdiv is less than 8, so the multiplication doesn't
246 		 * overflow an u64.
247 		 */
248 		*wf = (typeof(*wf)){
249 			.period_length_ns =
250 				DIV_ROUND_UP_ULL((u64)(cnt_period + 1) * NSEC_PER_SEC << clkdiv, clk_rate),
251 			.duty_length_ns =
252 				DIV_ROUND_UP_ULL((u64)(cnt_duty + 1) * NSEC_PER_SEC << clkdiv, clk_rate),
253 		};
254 	} else {
255 		clkdiv = 0;
256 		cnt_period = 0;
257 		cnt_duty = 0;
258 
259 		/*
260 		 * .enable = 0 is also used for too small duty_cycle values, so
261 		 * report the HW as being enabled to communicate the minimal
262 		 * period.
263 		 */
264 		*wf = (typeof(*wf)){
265 			.period_length_ns =
266 				DIV_ROUND_UP_ULL(NSEC_PER_SEC, clk_rate),
267 			.duty_length_ns = 0,
268 		};
269 	}
270 
271 	dev_dbg(&chip->dev, "pwm#%u: ENABLE: %x, CLKDIV: %x, PERIOD: %x, DUTY: %x @%lu -> %lld/%lld\n",
272 		pwm->hwpwm, wfhw->enable, clkdiv, cnt_period, cnt_duty, clk_rate,
273 		wf->duty_length_ns, wf->period_length_ns);
274 
275 	return 0;
276 }
277 
278 static int pwm_mediatek_read_waveform(struct pwm_chip *chip,
279 				      struct pwm_device *pwm, void *_wfhw)
280 {
281 	struct pwm_mediatek_waveform *wfhw = _wfhw;
282 	struct pwm_mediatek_chip *pc = to_pwm_mediatek_chip(chip);
283 	u32 enable, clkdiv, cnt_period, cnt_duty;
284 	u32 reg_width = PWMDWIDTH, reg_thres = PWMTHRES;
285 	int ret;
286 
287 	ret = pwm_mediatek_clk_enable(pc, pwm->hwpwm);
288 	if (ret < 0)
289 		return ret;
290 
291 	enable = readl(pc->regs) & BIT(pwm->hwpwm);
292 
293 	if (enable) {
294 		if (pc->soc->pwm45_fixup && pwm->hwpwm > 2) {
295 			/*
296 			 * PWM[4,5] has distinct offset for PWMDWIDTH and PWMTHRES
297 			 * from the other PWMs on MT7623.
298 			 */
299 			reg_width = PWM45DWIDTH_FIXUP;
300 			reg_thres = PWM45THRES_FIXUP;
301 		}
302 
303 		clkdiv = FIELD_GET(PWMCON_CLKDIV, pwm_mediatek_readl(pc, pwm->hwpwm, PWMCON));
304 		cnt_period = FIELD_GET(PWMDWIDTH_PERIOD, pwm_mediatek_readl(pc, pwm->hwpwm, reg_width));
305 		cnt_duty = FIELD_GET(PWMTHRES_DUTY, pwm_mediatek_readl(pc, pwm->hwpwm, reg_thres));
306 
307 		*wfhw = (typeof(*wfhw)){
308 			.enable = enable,
309 			.con = BIT(15) | clkdiv,
310 			.width = cnt_period,
311 			.thres = cnt_duty,
312 		};
313 	} else {
314 		*wfhw = (typeof(*wfhw)){
315 			.enable = 0,
316 		};
317 	}
318 
319 	pwm_mediatek_clk_disable(pc, pwm->hwpwm);
320 
321 	return ret;
322 }
323 
324 static int pwm_mediatek_write_waveform(struct pwm_chip *chip,
325 				       struct pwm_device *pwm, const void *_wfhw)
326 {
327 	const struct pwm_mediatek_waveform *wfhw = _wfhw;
328 	struct pwm_mediatek_chip *pc = to_pwm_mediatek_chip(chip);
329 	u32 ctrl;
330 	int ret;
331 
332 	ret = pwm_mediatek_clk_enable(pc, pwm->hwpwm);
333 	if (ret < 0)
334 		return ret;
335 
336 	ctrl = readl(pc->regs);
337 
338 	if (wfhw->enable) {
339 		u32 reg_width = PWMDWIDTH, reg_thres = PWMTHRES;
340 
341 		if (pc->soc->pwm45_fixup && pwm->hwpwm > 2) {
342 			/*
343 			 * PWM[4,5] has distinct offset for PWMDWIDTH and PWMTHRES
344 			 * from the other PWMs on MT7623.
345 			 */
346 			reg_width = PWM45DWIDTH_FIXUP;
347 			reg_thres = PWM45THRES_FIXUP;
348 		}
349 
350 		if (!(ctrl & BIT(pwm->hwpwm))) {
351 			/*
352 			 * The clks are already on, just increasing the usage
353 			 * counter doesn't fail.
354 			 */
355 			ret = pwm_mediatek_clk_enable(pc, pwm->hwpwm);
356 			if (unlikely(ret < 0))
357 				goto out;
358 
359 			ctrl |= BIT(pwm->hwpwm);
360 			writel(ctrl, pc->regs);
361 		}
362 
363 		/* Make sure we use the bus clock and not the 26MHz clock */
364 		if (pc->soc->pwm_ck_26m_sel_reg)
365 			writel(0, pc->regs + pc->soc->pwm_ck_26m_sel_reg);
366 
367 		pwm_mediatek_writel(pc, pwm->hwpwm, PWMCON, BIT(15) | wfhw->con);
368 		pwm_mediatek_writel(pc, pwm->hwpwm, reg_width, wfhw->width);
369 		pwm_mediatek_writel(pc, pwm->hwpwm, reg_thres, wfhw->thres);
370 	} else {
371 		if (ctrl & BIT(pwm->hwpwm)) {
372 			ctrl &= ~BIT(pwm->hwpwm);
373 			writel(ctrl, pc->regs);
374 
375 			pwm_mediatek_clk_disable(pc, pwm->hwpwm);
376 		}
377 	}
378 
379 out:
380 	pwm_mediatek_clk_disable(pc, pwm->hwpwm);
381 
382 	return ret;
383 }
384 
385 static const struct pwm_ops pwm_mediatek_ops = {
386 	.sizeof_wfhw = sizeof(struct pwm_mediatek_waveform),
387 	.round_waveform_tohw = pwm_mediatek_round_waveform_tohw,
388 	.round_waveform_fromhw = pwm_mediatek_round_waveform_fromhw,
389 	.read_waveform = pwm_mediatek_read_waveform,
390 	.write_waveform = pwm_mediatek_write_waveform,
391 };
392 
393 static int pwm_mediatek_init_used_clks(struct pwm_mediatek_chip *pc)
394 {
395 	const struct pwm_mediatek_of_data *soc = pc->soc;
396 	unsigned int hwpwm;
397 	u32 enabled, handled = 0;
398 	int ret;
399 
400 	ret = clk_prepare_enable(pc->clk_top);
401 	if (ret)
402 		return ret;
403 
404 	ret = clk_prepare_enable(pc->clk_main);
405 	if (ret)
406 		goto err_enable_main;
407 
408 	enabled = readl(pc->regs) & GENMASK(soc->num_pwms - 1, 0);
409 
410 	while (enabled & ~handled) {
411 		hwpwm = ilog2(enabled & ~handled);
412 
413 		ret = pwm_mediatek_clk_enable(pc, hwpwm);
414 		if (ret) {
415 			while (handled) {
416 				hwpwm = ilog2(handled);
417 
418 				pwm_mediatek_clk_disable(pc, hwpwm);
419 				handled &= ~BIT(hwpwm);
420 			}
421 
422 			break;
423 		}
424 
425 		handled |= BIT(hwpwm);
426 	}
427 
428 	clk_disable_unprepare(pc->clk_main);
429 err_enable_main:
430 
431 	clk_disable_unprepare(pc->clk_top);
432 
433 	return ret;
434 }
435 
436 static int pwm_mediatek_probe(struct platform_device *pdev)
437 {
438 	struct pwm_chip *chip;
439 	struct pwm_mediatek_chip *pc;
440 	const struct pwm_mediatek_of_data *soc;
441 	unsigned int i;
442 	int ret;
443 
444 	soc = of_device_get_match_data(&pdev->dev);
445 
446 	chip = devm_pwmchip_alloc(&pdev->dev, soc->num_pwms,
447 				  struct_size(pc, clk_pwms, soc->num_pwms));
448 	if (IS_ERR(chip))
449 		return PTR_ERR(chip);
450 	pc = to_pwm_mediatek_chip(chip);
451 
452 	pc->soc = soc;
453 
454 	pc->regs = devm_platform_ioremap_resource(pdev, 0);
455 	if (IS_ERR(pc->regs))
456 		return PTR_ERR(pc->regs);
457 
458 	pc->clk_top = devm_clk_get(&pdev->dev, "top");
459 	if (IS_ERR(pc->clk_top))
460 		return dev_err_probe(&pdev->dev, PTR_ERR(pc->clk_top),
461 				     "Failed to get top clock\n");
462 
463 	pc->clk_main = devm_clk_get(&pdev->dev, "main");
464 	if (IS_ERR(pc->clk_main))
465 		return dev_err_probe(&pdev->dev, PTR_ERR(pc->clk_main),
466 				     "Failed to get main clock\n");
467 
468 	for (i = 0; i < soc->num_pwms; i++) {
469 		char name[8];
470 
471 		snprintf(name, sizeof(name), "pwm%d", i + 1);
472 
473 		pc->clk_pwms[i].clk = devm_clk_get(&pdev->dev, name);
474 		if (IS_ERR(pc->clk_pwms[i].clk))
475 			return dev_err_probe(&pdev->dev, PTR_ERR(pc->clk_pwms[i].clk),
476 					     "Failed to get %s clock\n", name);
477 
478 		ret = devm_clk_rate_exclusive_get(&pdev->dev, pc->clk_pwms[i].clk);
479 		if (ret)
480 			return dev_err_probe(&pdev->dev, ret,
481 					     "Failed to lock clock rate for %s\n", name);
482 	}
483 
484 	ret = pwm_mediatek_init_used_clks(pc);
485 	if (ret)
486 		return dev_err_probe(&pdev->dev, ret, "Failed to initialize used clocks\n");
487 
488 	chip->ops = &pwm_mediatek_ops;
489 
490 	ret = devm_pwmchip_add(&pdev->dev, chip);
491 	if (ret < 0)
492 		return dev_err_probe(&pdev->dev, ret, "pwmchip_add() failed\n");
493 
494 	return 0;
495 }
496 
497 static const struct pwm_mediatek_of_data mt2712_pwm_data = {
498 	.num_pwms = 8,
499 	.pwm45_fixup = false,
500 	.chanreg_base = 0x10,
501 	.chanreg_width = 0x40,
502 };
503 
504 static const struct pwm_mediatek_of_data mt6795_pwm_data = {
505 	.num_pwms = 7,
506 	.pwm45_fixup = false,
507 	.chanreg_base = 0x10,
508 	.chanreg_width = 0x40,
509 };
510 
511 static const struct pwm_mediatek_of_data mt7622_pwm_data = {
512 	.num_pwms = 6,
513 	.pwm45_fixup = false,
514 	.pwm_ck_26m_sel_reg = PWM_CK_26M_SEL,
515 	.chanreg_base = 0x10,
516 	.chanreg_width = 0x40,
517 };
518 
519 static const struct pwm_mediatek_of_data mt7623_pwm_data = {
520 	.num_pwms = 5,
521 	.pwm45_fixup = true,
522 	.chanreg_base = 0x10,
523 	.chanreg_width = 0x40,
524 };
525 
526 static const struct pwm_mediatek_of_data mt7628_pwm_data = {
527 	.num_pwms = 4,
528 	.pwm45_fixup = true,
529 	.chanreg_base = 0x10,
530 	.chanreg_width = 0x40,
531 };
532 
533 static const struct pwm_mediatek_of_data mt7629_pwm_data = {
534 	.num_pwms = 1,
535 	.pwm45_fixup = false,
536 	.chanreg_base = 0x10,
537 	.chanreg_width = 0x40,
538 };
539 
540 static const struct pwm_mediatek_of_data mt7981_pwm_data = {
541 	.num_pwms = 3,
542 	.pwm45_fixup = false,
543 	.pwm_ck_26m_sel_reg = PWM_CK_26M_SEL,
544 	.chanreg_base = 0x80,
545 	.chanreg_width = 0x40,
546 };
547 
548 static const struct pwm_mediatek_of_data mt7986_pwm_data = {
549 	.num_pwms = 2,
550 	.pwm45_fixup = false,
551 	.pwm_ck_26m_sel_reg = PWM_CK_26M_SEL,
552 	.chanreg_base = 0x10,
553 	.chanreg_width = 0x40,
554 };
555 
556 static const struct pwm_mediatek_of_data mt7988_pwm_data = {
557 	.num_pwms = 8,
558 	.pwm45_fixup = false,
559 	.chanreg_base = 0x80,
560 	.chanreg_width = 0x40,
561 };
562 
563 static const struct pwm_mediatek_of_data mt8183_pwm_data = {
564 	.num_pwms = 4,
565 	.pwm45_fixup = false,
566 	.pwm_ck_26m_sel_reg = PWM_CK_26M_SEL,
567 	.chanreg_base = 0x10,
568 	.chanreg_width = 0x40,
569 };
570 
571 static const struct pwm_mediatek_of_data mt8365_pwm_data = {
572 	.num_pwms = 3,
573 	.pwm45_fixup = false,
574 	.pwm_ck_26m_sel_reg = PWM_CK_26M_SEL,
575 	.chanreg_base = 0x10,
576 	.chanreg_width = 0x40,
577 };
578 
579 static const struct pwm_mediatek_of_data mt8516_pwm_data = {
580 	.num_pwms = 5,
581 	.pwm45_fixup = false,
582 	.pwm_ck_26m_sel_reg = PWM_CK_26M_SEL,
583 	.chanreg_base = 0x10,
584 	.chanreg_width = 0x40,
585 };
586 
587 static const struct pwm_mediatek_of_data mt6991_pwm_data = {
588 	.num_pwms = 4,
589 	.pwm45_fixup = false,
590 	.pwm_ck_26m_sel_reg = PWM_CK_26M_SEL_V3,
591 	.chanreg_base = 0x100,
592 	.chanreg_width = 0x100,
593 };
594 
595 static const struct of_device_id pwm_mediatek_of_match[] = {
596 	{ .compatible = "mediatek,mt2712-pwm", .data = &mt2712_pwm_data },
597 	{ .compatible = "mediatek,mt6795-pwm", .data = &mt6795_pwm_data },
598 	{ .compatible = "mediatek,mt6991-pwm", .data = &mt6991_pwm_data },
599 	{ .compatible = "mediatek,mt7622-pwm", .data = &mt7622_pwm_data },
600 	{ .compatible = "mediatek,mt7623-pwm", .data = &mt7623_pwm_data },
601 	{ .compatible = "mediatek,mt7628-pwm", .data = &mt7628_pwm_data },
602 	{ .compatible = "mediatek,mt7629-pwm", .data = &mt7629_pwm_data },
603 	{ .compatible = "mediatek,mt7981-pwm", .data = &mt7981_pwm_data },
604 	{ .compatible = "mediatek,mt7986-pwm", .data = &mt7986_pwm_data },
605 	{ .compatible = "mediatek,mt7988-pwm", .data = &mt7988_pwm_data },
606 	{ .compatible = "mediatek,mt8183-pwm", .data = &mt8183_pwm_data },
607 	{ .compatible = "mediatek,mt8365-pwm", .data = &mt8365_pwm_data },
608 	{ .compatible = "mediatek,mt8516-pwm", .data = &mt8516_pwm_data },
609 	{ },
610 };
611 MODULE_DEVICE_TABLE(of, pwm_mediatek_of_match);
612 
613 static struct platform_driver pwm_mediatek_driver = {
614 	.driver = {
615 		.name = "pwm-mediatek",
616 		.of_match_table = pwm_mediatek_of_match,
617 	},
618 	.probe = pwm_mediatek_probe,
619 };
620 module_platform_driver(pwm_mediatek_driver);
621 
622 MODULE_AUTHOR("John Crispin <blogic@openwrt.org>");
623 MODULE_DESCRIPTION("MediaTek general purpose Pulse Width Modulator driver");
624 MODULE_LICENSE("GPL v2");
625