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