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