xref: /linux/drivers/pwm/pwm-mediatek.c (revision 0d5ec7919f3747193f051036b2301734a4b5e1d6)
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 *
74 to_pwm_mediatek_chip(struct pwm_chip *chip)
75 {
76 	return pwmchip_get_drvdata(chip);
77 }
78 
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 
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 
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 
124 static int pwm_mediatek_config(struct pwm_chip *chip, struct pwm_device *pwm,
125 			       int duty_ns, int period_ns)
126 {
127 	struct pwm_mediatek_chip *pc = to_pwm_mediatek_chip(chip);
128 	u32 clkdiv = 0, cnt_period, cnt_duty, reg_width = PWMDWIDTH,
129 	    reg_thres = PWMTHRES;
130 	unsigned long clk_rate;
131 	u64 resolution;
132 	int ret;
133 
134 	ret = pwm_mediatek_clk_enable(chip, pwm);
135 	if (ret < 0)
136 		return ret;
137 
138 	clk_rate = clk_get_rate(pc->clk_pwms[pwm->hwpwm]);
139 	if (!clk_rate) {
140 		ret = -EINVAL;
141 		goto out;
142 	}
143 
144 	/* Make sure we use the bus clock and not the 26MHz clock */
145 	if (pc->soc->pwm_ck_26m_sel_reg)
146 		writel(0, pc->regs + pc->soc->pwm_ck_26m_sel_reg);
147 
148 	/* Using resolution in picosecond gets accuracy higher */
149 	resolution = (u64)NSEC_PER_SEC * 1000;
150 	do_div(resolution, clk_rate);
151 
152 	cnt_period = DIV_ROUND_CLOSEST_ULL((u64)period_ns * 1000, resolution);
153 	while (cnt_period > 8191) {
154 		resolution *= 2;
155 		clkdiv++;
156 		cnt_period = DIV_ROUND_CLOSEST_ULL((u64)period_ns * 1000,
157 						   resolution);
158 	}
159 
160 	if (clkdiv > PWM_CLK_DIV_MAX) {
161 		dev_err(pwmchip_parent(chip), "period of %d ns not supported\n", period_ns);
162 		ret = -EINVAL;
163 		goto out;
164 	}
165 
166 	if (pc->soc->pwm45_fixup && pwm->hwpwm > 2) {
167 		/*
168 		 * PWM[4,5] has distinct offset for PWMDWIDTH and PWMTHRES
169 		 * from the other PWMs on MT7623.
170 		 */
171 		reg_width = PWM45DWIDTH_FIXUP;
172 		reg_thres = PWM45THRES_FIXUP;
173 	}
174 
175 	cnt_duty = DIV_ROUND_CLOSEST_ULL((u64)duty_ns * 1000, resolution);
176 	pwm_mediatek_writel(pc, pwm->hwpwm, PWMCON, BIT(15) | clkdiv);
177 	pwm_mediatek_writel(pc, pwm->hwpwm, reg_width, cnt_period);
178 	pwm_mediatek_writel(pc, pwm->hwpwm, reg_thres, cnt_duty);
179 
180 out:
181 	pwm_mediatek_clk_disable(chip, pwm);
182 
183 	return ret;
184 }
185 
186 static int pwm_mediatek_enable(struct pwm_chip *chip, struct pwm_device *pwm)
187 {
188 	struct pwm_mediatek_chip *pc = to_pwm_mediatek_chip(chip);
189 	u32 value;
190 	int ret;
191 
192 	ret = pwm_mediatek_clk_enable(chip, pwm);
193 	if (ret < 0)
194 		return ret;
195 
196 	value = readl(pc->regs);
197 	value |= BIT(pwm->hwpwm);
198 	writel(value, pc->regs);
199 
200 	return 0;
201 }
202 
203 static void pwm_mediatek_disable(struct pwm_chip *chip, struct pwm_device *pwm)
204 {
205 	struct pwm_mediatek_chip *pc = to_pwm_mediatek_chip(chip);
206 	u32 value;
207 
208 	value = readl(pc->regs);
209 	value &= ~BIT(pwm->hwpwm);
210 	writel(value, pc->regs);
211 
212 	pwm_mediatek_clk_disable(chip, pwm);
213 }
214 
215 static int pwm_mediatek_apply(struct pwm_chip *chip, struct pwm_device *pwm,
216 			      const struct pwm_state *state)
217 {
218 	int err;
219 
220 	if (state->polarity != PWM_POLARITY_NORMAL)
221 		return -EINVAL;
222 
223 	if (!state->enabled) {
224 		if (pwm->state.enabled)
225 			pwm_mediatek_disable(chip, pwm);
226 
227 		return 0;
228 	}
229 
230 	err = pwm_mediatek_config(chip, pwm, state->duty_cycle, state->period);
231 	if (err)
232 		return err;
233 
234 	if (!pwm->state.enabled)
235 		err = pwm_mediatek_enable(chip, pwm);
236 
237 	return err;
238 }
239 
240 static const struct pwm_ops pwm_mediatek_ops = {
241 	.apply = pwm_mediatek_apply,
242 };
243 
244 static int pwm_mediatek_probe(struct platform_device *pdev)
245 {
246 	struct pwm_chip *chip;
247 	struct pwm_mediatek_chip *pc;
248 	const struct pwm_mediatek_of_data *soc;
249 	unsigned int i;
250 	int ret;
251 
252 	soc = of_device_get_match_data(&pdev->dev);
253 
254 	chip = devm_pwmchip_alloc(&pdev->dev, soc->num_pwms, sizeof(*pc));
255 	if (IS_ERR(chip))
256 		return PTR_ERR(chip);
257 	pc = to_pwm_mediatek_chip(chip);
258 
259 	pc->soc = soc;
260 
261 	pc->regs = devm_platform_ioremap_resource(pdev, 0);
262 	if (IS_ERR(pc->regs))
263 		return PTR_ERR(pc->regs);
264 
265 	pc->clk_pwms = devm_kmalloc_array(&pdev->dev, soc->num_pwms,
266 				    sizeof(*pc->clk_pwms), GFP_KERNEL);
267 	if (!pc->clk_pwms)
268 		return -ENOMEM;
269 
270 	pc->clk_top = devm_clk_get(&pdev->dev, "top");
271 	if (IS_ERR(pc->clk_top))
272 		return dev_err_probe(&pdev->dev, PTR_ERR(pc->clk_top),
273 				     "Failed to get top clock\n");
274 
275 	pc->clk_main = devm_clk_get(&pdev->dev, "main");
276 	if (IS_ERR(pc->clk_main))
277 		return dev_err_probe(&pdev->dev, PTR_ERR(pc->clk_main),
278 				     "Failed to get main clock\n");
279 
280 	for (i = 0; i < soc->num_pwms; i++) {
281 		char name[8];
282 
283 		snprintf(name, sizeof(name), "pwm%d", i + 1);
284 
285 		pc->clk_pwms[i] = devm_clk_get(&pdev->dev, name);
286 		if (IS_ERR(pc->clk_pwms[i]))
287 			return dev_err_probe(&pdev->dev, PTR_ERR(pc->clk_pwms[i]),
288 					     "Failed to get %s clock\n", name);
289 	}
290 
291 	chip->ops = &pwm_mediatek_ops;
292 
293 	ret = devm_pwmchip_add(&pdev->dev, chip);
294 	if (ret < 0)
295 		return dev_err_probe(&pdev->dev, ret, "pwmchip_add() failed\n");
296 
297 	return 0;
298 }
299 
300 static const struct pwm_mediatek_of_data mt2712_pwm_data = {
301 	.num_pwms = 8,
302 	.pwm45_fixup = false,
303 	.reg_offset = mtk_pwm_reg_offset_v1,
304 };
305 
306 static const struct pwm_mediatek_of_data mt6795_pwm_data = {
307 	.num_pwms = 7,
308 	.pwm45_fixup = false,
309 	.reg_offset = mtk_pwm_reg_offset_v1,
310 };
311 
312 static const struct pwm_mediatek_of_data mt7622_pwm_data = {
313 	.num_pwms = 6,
314 	.pwm45_fixup = false,
315 	.pwm_ck_26m_sel_reg = PWM_CK_26M_SEL,
316 	.reg_offset = mtk_pwm_reg_offset_v1,
317 };
318 
319 static const struct pwm_mediatek_of_data mt7623_pwm_data = {
320 	.num_pwms = 5,
321 	.pwm45_fixup = true,
322 	.reg_offset = mtk_pwm_reg_offset_v1,
323 };
324 
325 static const struct pwm_mediatek_of_data mt7628_pwm_data = {
326 	.num_pwms = 4,
327 	.pwm45_fixup = true,
328 	.reg_offset = mtk_pwm_reg_offset_v1,
329 };
330 
331 static const struct pwm_mediatek_of_data mt7629_pwm_data = {
332 	.num_pwms = 1,
333 	.pwm45_fixup = false,
334 	.reg_offset = mtk_pwm_reg_offset_v1,
335 };
336 
337 static const struct pwm_mediatek_of_data mt7981_pwm_data = {
338 	.num_pwms = 3,
339 	.pwm45_fixup = false,
340 	.pwm_ck_26m_sel_reg = PWM_CK_26M_SEL,
341 	.reg_offset = mtk_pwm_reg_offset_v2,
342 };
343 
344 static const struct pwm_mediatek_of_data mt7986_pwm_data = {
345 	.num_pwms = 2,
346 	.pwm45_fixup = false,
347 	.pwm_ck_26m_sel_reg = PWM_CK_26M_SEL,
348 	.reg_offset = mtk_pwm_reg_offset_v1,
349 };
350 
351 static const struct pwm_mediatek_of_data mt7988_pwm_data = {
352 	.num_pwms = 8,
353 	.pwm45_fixup = false,
354 	.reg_offset = mtk_pwm_reg_offset_v2,
355 };
356 
357 static const struct pwm_mediatek_of_data mt8183_pwm_data = {
358 	.num_pwms = 4,
359 	.pwm45_fixup = false,
360 	.pwm_ck_26m_sel_reg = PWM_CK_26M_SEL,
361 	.reg_offset = mtk_pwm_reg_offset_v1,
362 };
363 
364 static const struct pwm_mediatek_of_data mt8365_pwm_data = {
365 	.num_pwms = 3,
366 	.pwm45_fixup = false,
367 	.pwm_ck_26m_sel_reg = PWM_CK_26M_SEL,
368 	.reg_offset = mtk_pwm_reg_offset_v1,
369 };
370 
371 static const struct pwm_mediatek_of_data mt8516_pwm_data = {
372 	.num_pwms = 5,
373 	.pwm45_fixup = false,
374 	.pwm_ck_26m_sel_reg = PWM_CK_26M_SEL,
375 	.reg_offset = mtk_pwm_reg_offset_v1,
376 };
377 
378 static const struct pwm_mediatek_of_data mt6991_pwm_data = {
379 	.num_pwms = 4,
380 	.pwm45_fixup = false,
381 	.pwm_ck_26m_sel_reg = PWM_CK_26M_SEL_V3,
382 	.reg_offset = mtk_pwm_reg_offset_v3,
383 };
384 
385 static const struct of_device_id pwm_mediatek_of_match[] = {
386 	{ .compatible = "mediatek,mt2712-pwm", .data = &mt2712_pwm_data },
387 	{ .compatible = "mediatek,mt6795-pwm", .data = &mt6795_pwm_data },
388 	{ .compatible = "mediatek,mt6991-pwm", .data = &mt6991_pwm_data },
389 	{ .compatible = "mediatek,mt7622-pwm", .data = &mt7622_pwm_data },
390 	{ .compatible = "mediatek,mt7623-pwm", .data = &mt7623_pwm_data },
391 	{ .compatible = "mediatek,mt7628-pwm", .data = &mt7628_pwm_data },
392 	{ .compatible = "mediatek,mt7629-pwm", .data = &mt7629_pwm_data },
393 	{ .compatible = "mediatek,mt7981-pwm", .data = &mt7981_pwm_data },
394 	{ .compatible = "mediatek,mt7986-pwm", .data = &mt7986_pwm_data },
395 	{ .compatible = "mediatek,mt7988-pwm", .data = &mt7988_pwm_data },
396 	{ .compatible = "mediatek,mt8183-pwm", .data = &mt8183_pwm_data },
397 	{ .compatible = "mediatek,mt8365-pwm", .data = &mt8365_pwm_data },
398 	{ .compatible = "mediatek,mt8516-pwm", .data = &mt8516_pwm_data },
399 	{ },
400 };
401 MODULE_DEVICE_TABLE(of, pwm_mediatek_of_match);
402 
403 static struct platform_driver pwm_mediatek_driver = {
404 	.driver = {
405 		.name = "pwm-mediatek",
406 		.of_match_table = pwm_mediatek_of_match,
407 	},
408 	.probe = pwm_mediatek_probe,
409 };
410 module_platform_driver(pwm_mediatek_driver);
411 
412 MODULE_AUTHOR("John Crispin <blogic@openwrt.org>");
413 MODULE_DESCRIPTION("MediaTek general purpose Pulse Width Modulator driver");
414 MODULE_LICENSE("GPL v2");
415