1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3 * PWM driver for Rockchip SoCs
4 *
5 * Copyright (C) 2014 Beniamino Galvani <b.galvani@gmail.com>
6 * Copyright (C) 2014 ROCKCHIP, Inc.
7 */
8
9 #include <linux/clk.h>
10 #include <linux/interrupt.h>
11 #include <linux/io.h>
12 #include <linux/iopoll.h>
13 #include <linux/irq.h>
14 #include <linux/module.h>
15 #include <linux/of.h>
16 #include <linux/of_device.h>
17 #include <linux/pinctrl/consumer.h>
18 #include <linux/platform_device.h>
19 #include <linux/pwm.h>
20 #include <linux/time.h>
21 #include "pwm-rockchip.h"
22
23 #define PWM_MAX_CHANNEL_NUM 4
24
25 #define PWM_CTRL_TIMER_EN (1 << 0)
26 #define PWM_CTRL_OUTPUT_EN (1 << 3)
27
28 #define PWM_ENABLE (1 << 0)
29 #define PWM_MODE_SHIFT 1
30 #define PWM_MODE_MASK (0x3 << PWM_MODE_SHIFT)
31 #define PWM_ONESHOT (0 << PWM_MODE_SHIFT)
32 #define PWM_CONTINUOUS (1 << PWM_MODE_SHIFT)
33 #define PWM_CAPTURE (2 << PWM_MODE_SHIFT)
34 #define PWM_DUTY_POSITIVE (1 << 3)
35 #define PWM_DUTY_NEGATIVE (0 << 3)
36 #define PWM_INACTIVE_NEGATIVE (0 << 4)
37 #define PWM_INACTIVE_POSITIVE (1 << 4)
38 #define PWM_POLARITY_MASK (PWM_DUTY_POSITIVE | PWM_INACTIVE_POSITIVE)
39 #define PWM_OUTPUT_LEFT (0 << 5)
40 #define PWM_OUTPUT_CENTER (1 << 5)
41 #define PWM_LOCK_EN (1 << 6)
42 #define PWM_LP_DISABLE (0 << 8)
43 #define PWM_CLK_SEL_SHIFT 9
44 #define PWM_CLK_SEL_MASK (1 << PWM_CLK_SEL_SHIFT)
45 #define PWM_SEL_NO_SCALED_CLOCK (0 << PWM_CLK_SEL_SHIFT)
46 #define PWM_SEL_SCALED_CLOCK (1 << PWM_CLK_SEL_SHIFT)
47 #define PWM_PRESCELE_SHIFT 12
48 #define PWM_PRESCALE_MASK (0x3 << PWM_PRESCELE_SHIFT)
49 #define PWM_SCALE_SHIFT 16
50 #define PWM_SCALE_MASK (0xff << PWM_SCALE_SHIFT)
51
52 #define PWM_ONESHOT_COUNT_SHIFT 24
53 #define PWM_ONESHOT_COUNT_MASK (0xff << PWM_ONESHOT_COUNT_SHIFT)
54 #define PWM_ONESHOT_COUNT_MAX 256
55
56 #define PWM_REG_INTSTS(n) ((3 - (n)) * 0x10 + 0x10)
57 #define PWM_REG_INT_EN(n) ((3 - (n)) * 0x10 + 0x14)
58
59 #define PWM_CH_INT(n) BIT(n)
60
61 struct rockchip_pwm_chip {
62 struct pwm_chip chip;
63 struct clk *clk;
64 struct clk *pclk;
65 struct pinctrl *pinctrl;
66 struct pinctrl_state *active_state;
67 const struct rockchip_pwm_data *data;
68 void __iomem *base;
69 unsigned long clk_rate;
70 bool vop_pwm_en; /* indicate voppwm mirror register state */
71 bool center_aligned;
72 bool oneshot_en;
73 int channel_id;
74 int irq;
75 };
76
77 struct rockchip_pwm_regs {
78 unsigned long duty;
79 unsigned long period;
80 unsigned long cntr;
81 unsigned long ctrl;
82 };
83
84 struct rockchip_pwm_data {
85 struct rockchip_pwm_regs regs;
86 unsigned int prescaler;
87 bool supports_polarity;
88 bool supports_lock;
89 bool vop_pwm;
90 u32 enable_conf;
91 u32 enable_conf_mask;
92 };
93
to_rockchip_pwm_chip(struct pwm_chip * c)94 static inline struct rockchip_pwm_chip *to_rockchip_pwm_chip(struct pwm_chip *c)
95 {
96 return container_of(c, struct rockchip_pwm_chip, chip);
97 }
98
rockchip_pwm_get_state(struct pwm_chip * chip,struct pwm_device * pwm,struct pwm_state * state)99 static void rockchip_pwm_get_state(struct pwm_chip *chip,
100 struct pwm_device *pwm,
101 struct pwm_state *state)
102 {
103 struct rockchip_pwm_chip *pc = to_rockchip_pwm_chip(chip);
104 u32 enable_conf = pc->data->enable_conf;
105 u64 tmp;
106 u32 val;
107 u32 dclk_div;
108 int ret;
109
110 if (!pc->oneshot_en) {
111 ret = clk_enable(pc->pclk);
112 if (ret)
113 return;
114 }
115
116 dclk_div = pc->oneshot_en ? 2 : 1;
117
118 tmp = readl_relaxed(pc->base + pc->data->regs.period);
119 tmp *= dclk_div * pc->data->prescaler * NSEC_PER_SEC;
120 state->period = DIV_ROUND_CLOSEST_ULL(tmp, pc->clk_rate);
121
122 tmp = readl_relaxed(pc->base + pc->data->regs.duty);
123 tmp *= dclk_div * pc->data->prescaler * NSEC_PER_SEC;
124 state->duty_cycle = DIV_ROUND_CLOSEST_ULL(tmp, pc->clk_rate);
125
126 val = readl_relaxed(pc->base + pc->data->regs.ctrl);
127 if (pc->oneshot_en)
128 enable_conf &= ~PWM_CONTINUOUS;
129 state->enabled = (val & enable_conf) == enable_conf;
130
131 if (pc->data->supports_polarity && !(val & PWM_DUTY_POSITIVE))
132 state->polarity = PWM_POLARITY_INVERSED;
133 else
134 state->polarity = PWM_POLARITY_NORMAL;
135
136 if (!pc->oneshot_en)
137 clk_disable(pc->pclk);
138 }
139
rockchip_pwm_oneshot_irq(int irq,void * data)140 static irqreturn_t rockchip_pwm_oneshot_irq(int irq, void *data)
141 {
142 struct rockchip_pwm_chip *pc = data;
143 struct pwm_state state;
144 unsigned int id = pc->channel_id;
145 int val;
146
147 if (id > 3)
148 return IRQ_NONE;
149 val = readl_relaxed(pc->base + PWM_REG_INTSTS(id));
150
151 if ((val & PWM_CH_INT(id)) == 0)
152 return IRQ_NONE;
153
154 writel_relaxed(PWM_CH_INT(id), pc->base + PWM_REG_INTSTS(id));
155
156 /*
157 * Set pwm state to disabled when the oneshot mode finished.
158 */
159 pwm_get_state(&pc->chip.pwms[0], &state);
160 state.enabled = false;
161 pwm_apply_state(&pc->chip.pwms[0], &state);
162
163 rockchip_pwm_oneshot_callback(&pc->chip.pwms[0], &state);
164
165 return IRQ_HANDLED;
166 }
167
rockchip_pwm_config(struct pwm_chip * chip,struct pwm_device * pwm,const struct pwm_state * state)168 static void rockchip_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
169 const struct pwm_state *state)
170 {
171 struct rockchip_pwm_chip *pc = to_rockchip_pwm_chip(chip);
172 unsigned long period, duty;
173 unsigned long flags;
174 u64 div;
175 u32 ctrl;
176 u8 dclk_div = 1;
177
178 #ifdef CONFIG_PWM_ROCKCHIP_ONESHOT
179 if (state->oneshot_count > 0 && state->oneshot_count <= PWM_ONESHOT_COUNT_MAX)
180 dclk_div = 2;
181 #endif
182
183 /*
184 * Since period and duty cycle registers have a width of 32
185 * bits, every possible input period can be obtained using the
186 * default prescaler value for all practical clock rate values.
187 */
188 div = (u64)pc->clk_rate * state->period;
189 period = DIV_ROUND_CLOSEST_ULL(div, dclk_div * pc->data->prescaler * NSEC_PER_SEC);
190
191 div = (u64)pc->clk_rate * state->duty_cycle;
192 duty = DIV_ROUND_CLOSEST_ULL(div, dclk_div * pc->data->prescaler * NSEC_PER_SEC);
193
194 local_irq_save(flags);
195 /*
196 * Lock the period and duty of previous configuration, then
197 * change the duty and period, that would not be effective.
198 */
199 ctrl = readl_relaxed(pc->base + pc->data->regs.ctrl);
200 if (pc->data->vop_pwm) {
201 if (pc->vop_pwm_en)
202 ctrl |= PWM_ENABLE;
203 else
204 ctrl &= ~PWM_ENABLE;
205 }
206
207 #ifdef CONFIG_PWM_ROCKCHIP_ONESHOT
208 if (state->oneshot_count > 0 && state->oneshot_count <= PWM_ONESHOT_COUNT_MAX) {
209 u32 int_ctrl;
210
211 /*
212 * This is a workaround, an uncertain waveform will be
213 * generated after oneshot ends. It is needed to enable
214 * the dclk scale function to resolve it. It doesn't
215 * matter what the scale factor is, just make sure the
216 * scale function is turned on, for which we set scale
217 * factor to 2.
218 */
219 ctrl &= ~PWM_SCALE_MASK;
220 ctrl |= (dclk_div / 2) << PWM_SCALE_SHIFT;
221 ctrl &= ~PWM_CLK_SEL_MASK;
222 ctrl |= PWM_SEL_SCALED_CLOCK;
223
224 pc->oneshot_en = true;
225 ctrl &= ~PWM_MODE_MASK;
226 ctrl |= PWM_ONESHOT;
227
228 ctrl &= ~PWM_ONESHOT_COUNT_MASK;
229 ctrl |= (state->oneshot_count - 1) << PWM_ONESHOT_COUNT_SHIFT;
230
231 int_ctrl = readl_relaxed(pc->base + PWM_REG_INT_EN(pc->channel_id));
232 int_ctrl |= PWM_CH_INT(pc->channel_id);
233 writel_relaxed(int_ctrl, pc->base + PWM_REG_INT_EN(pc->channel_id));
234 } else {
235 u32 int_ctrl;
236
237 ctrl &= ~PWM_SCALE_MASK;
238 ctrl &= ~PWM_CLK_SEL_MASK;
239 ctrl |= PWM_SEL_NO_SCALED_CLOCK;
240
241 if (state->oneshot_count)
242 dev_err(chip->dev, "Oneshot_count must be between 1 and 256.\n");
243
244 pc->oneshot_en = false;
245 ctrl &= ~PWM_MODE_MASK;
246 ctrl |= PWM_CONTINUOUS;
247
248 ctrl &= ~PWM_ONESHOT_COUNT_MASK;
249
250 int_ctrl = readl_relaxed(pc->base + PWM_REG_INT_EN(pc->channel_id));
251 int_ctrl &= ~PWM_CH_INT(pc->channel_id);
252 writel_relaxed(int_ctrl, pc->base + PWM_REG_INT_EN(pc->channel_id));
253 }
254 #endif
255
256 if (pc->data->supports_lock) {
257 ctrl |= PWM_LOCK_EN;
258 writel_relaxed(ctrl, pc->base + pc->data->regs.ctrl);
259 }
260
261 writel(period, pc->base + pc->data->regs.period);
262 writel(duty, pc->base + pc->data->regs.duty);
263
264 if (pc->data->supports_polarity) {
265 ctrl &= ~PWM_POLARITY_MASK;
266 if (state->polarity == PWM_POLARITY_INVERSED)
267 ctrl |= PWM_DUTY_NEGATIVE | PWM_INACTIVE_POSITIVE;
268 else
269 ctrl |= PWM_DUTY_POSITIVE | PWM_INACTIVE_NEGATIVE;
270 }
271
272 /*
273 * Unlock and set polarity at the same time,
274 * the configuration of duty, period and polarity
275 * would be effective together at next period.
276 */
277 if (pc->data->supports_lock)
278 ctrl &= ~PWM_LOCK_EN;
279
280 writel(ctrl, pc->base + pc->data->regs.ctrl);
281 local_irq_restore(flags);
282 }
283
rockchip_pwm_enable(struct pwm_chip * chip,struct pwm_device * pwm,bool enable)284 static int rockchip_pwm_enable(struct pwm_chip *chip,
285 struct pwm_device *pwm,
286 bool enable)
287 {
288 struct rockchip_pwm_chip *pc = to_rockchip_pwm_chip(chip);
289 u32 enable_conf = pc->data->enable_conf;
290 int ret;
291 u32 val;
292
293 if (enable) {
294 ret = clk_enable(pc->clk);
295 if (ret)
296 return ret;
297 }
298
299 val = readl_relaxed(pc->base + pc->data->regs.ctrl);
300 val &= ~pc->data->enable_conf_mask;
301
302 if (PWM_OUTPUT_CENTER & pc->data->enable_conf_mask) {
303 if (pc->center_aligned)
304 val |= PWM_OUTPUT_CENTER;
305 }
306
307 if (enable) {
308 val |= enable_conf;
309 if (pc->oneshot_en)
310 val &= ~PWM_CONTINUOUS;
311 } else {
312 val &= ~enable_conf;
313 }
314
315 writel_relaxed(val, pc->base + pc->data->regs.ctrl);
316 if (pc->data->vop_pwm)
317 pc->vop_pwm_en = enable;
318
319 if (!enable)
320 clk_disable(pc->clk);
321
322 return 0;
323 }
324
rockchip_pwm_apply(struct pwm_chip * chip,struct pwm_device * pwm,const struct pwm_state * state)325 static int rockchip_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
326 const struct pwm_state *state)
327 {
328 struct rockchip_pwm_chip *pc = to_rockchip_pwm_chip(chip);
329 struct pwm_state curstate;
330 bool enabled;
331 int ret = 0;
332
333 if (!pc->oneshot_en) {
334 ret = clk_enable(pc->pclk);
335 if (ret)
336 return ret;
337 }
338
339 pwm_get_state(pwm, &curstate);
340 enabled = curstate.enabled;
341
342 if (state->polarity != curstate.polarity && enabled &&
343 !pc->data->supports_lock) {
344 ret = rockchip_pwm_enable(chip, pwm, false);
345 if (ret)
346 goto out;
347 enabled = false;
348 }
349
350 rockchip_pwm_config(chip, pwm, state);
351 if (state->enabled != enabled) {
352 ret = rockchip_pwm_enable(chip, pwm, state->enabled);
353 if (ret)
354 goto out;
355 }
356
357 if (state->enabled)
358 ret = pinctrl_select_state(pc->pinctrl, pc->active_state);
359 out:
360 if (!pc->oneshot_en)
361 clk_disable(pc->pclk);
362
363 return ret;
364 }
365
366 static const struct pwm_ops rockchip_pwm_ops = {
367 .get_state = rockchip_pwm_get_state,
368 .apply = rockchip_pwm_apply,
369 .owner = THIS_MODULE,
370 };
371
372 static const struct rockchip_pwm_data pwm_data_v1 = {
373 .regs = {
374 .duty = 0x04,
375 .period = 0x08,
376 .cntr = 0x00,
377 .ctrl = 0x0c,
378 },
379 .prescaler = 2,
380 .supports_polarity = false,
381 .supports_lock = false,
382 .vop_pwm = false,
383 .enable_conf = PWM_CTRL_OUTPUT_EN | PWM_CTRL_TIMER_EN,
384 .enable_conf_mask = BIT(1) | BIT(3),
385 };
386
387 static const struct rockchip_pwm_data pwm_data_v2 = {
388 .regs = {
389 .duty = 0x08,
390 .period = 0x04,
391 .cntr = 0x00,
392 .ctrl = 0x0c,
393 },
394 .prescaler = 1,
395 .supports_polarity = true,
396 .supports_lock = false,
397 .vop_pwm = false,
398 .enable_conf = PWM_OUTPUT_LEFT | PWM_LP_DISABLE | PWM_ENABLE |
399 PWM_CONTINUOUS,
400 .enable_conf_mask = GENMASK(2, 0) | BIT(5) | BIT(8),
401 };
402
403 static const struct rockchip_pwm_data pwm_data_vop = {
404 .regs = {
405 .duty = 0x08,
406 .period = 0x04,
407 .cntr = 0x0c,
408 .ctrl = 0x00,
409 },
410 .prescaler = 1,
411 .supports_polarity = true,
412 .supports_lock = false,
413 .vop_pwm = true,
414 .enable_conf = PWM_OUTPUT_LEFT | PWM_LP_DISABLE | PWM_ENABLE |
415 PWM_CONTINUOUS,
416 .enable_conf_mask = GENMASK(2, 0) | BIT(5) | BIT(8),
417 };
418
419 static const struct rockchip_pwm_data pwm_data_v3 = {
420 .regs = {
421 .duty = 0x08,
422 .period = 0x04,
423 .cntr = 0x00,
424 .ctrl = 0x0c,
425 },
426 .prescaler = 1,
427 .supports_polarity = true,
428 .supports_lock = true,
429 .vop_pwm = false,
430 .enable_conf = PWM_OUTPUT_LEFT | PWM_LP_DISABLE | PWM_ENABLE |
431 PWM_CONTINUOUS,
432 .enable_conf_mask = GENMASK(2, 0) | BIT(5) | BIT(8),
433 };
434
435 static const struct of_device_id rockchip_pwm_dt_ids[] = {
436 { .compatible = "rockchip,rk2928-pwm", .data = &pwm_data_v1},
437 { .compatible = "rockchip,rk3288-pwm", .data = &pwm_data_v2},
438 { .compatible = "rockchip,vop-pwm", .data = &pwm_data_vop},
439 { .compatible = "rockchip,rk3328-pwm", .data = &pwm_data_v3},
440 { /* sentinel */ }
441 };
442 MODULE_DEVICE_TABLE(of, rockchip_pwm_dt_ids);
443
rockchip_pwm_get_channel_id(const char * name)444 static int rockchip_pwm_get_channel_id(const char *name)
445 {
446 int len = strlen(name);
447
448 return name[len - 2] - '0';
449 }
450
rockchip_pwm_probe(struct platform_device * pdev)451 static int rockchip_pwm_probe(struct platform_device *pdev)
452 {
453 const struct of_device_id *id;
454 struct rockchip_pwm_chip *pc;
455 struct resource *r;
456 u32 enable_conf, ctrl;
457 bool enabled;
458 int ret, count;
459
460 id = of_match_device(rockchip_pwm_dt_ids, &pdev->dev);
461 if (!id)
462 return -EINVAL;
463
464 pc = devm_kzalloc(&pdev->dev, sizeof(*pc), GFP_KERNEL);
465 if (!pc)
466 return -ENOMEM;
467
468 r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
469 pc->base = devm_ioremap(&pdev->dev, r->start,
470 resource_size(r));
471 if (IS_ERR(pc->base))
472 return PTR_ERR(pc->base);
473
474 pc->clk = devm_clk_get(&pdev->dev, "pwm");
475 if (IS_ERR(pc->clk)) {
476 pc->clk = devm_clk_get(&pdev->dev, NULL);
477 if (IS_ERR(pc->clk))
478 return dev_err_probe(&pdev->dev, PTR_ERR(pc->clk),
479 "Can't get bus clk\n");
480 }
481
482 count = of_count_phandle_with_args(pdev->dev.of_node,
483 "clocks", "#clock-cells");
484 if (count == 2)
485 pc->pclk = devm_clk_get(&pdev->dev, "pclk");
486 else
487 pc->pclk = pc->clk;
488
489 if (IS_ERR(pc->pclk)) {
490 ret = PTR_ERR(pc->pclk);
491 if (ret != -EPROBE_DEFER)
492 dev_err(&pdev->dev, "Can't get APB clk: %d\n", ret);
493 return ret;
494 }
495
496 ret = clk_prepare_enable(pc->clk);
497 if (ret) {
498 dev_err(&pdev->dev, "Can't prepare enable bus clk: %d\n", ret);
499 return ret;
500 }
501
502 ret = clk_prepare_enable(pc->pclk);
503 if (ret) {
504 dev_err(&pdev->dev, "Can't prepare enable APB clk: %d\n", ret);
505 goto err_clk;
506 }
507
508 pc->channel_id = rockchip_pwm_get_channel_id(pdev->dev.of_node->full_name);
509 if (pc->channel_id < 0 || pc->channel_id >= PWM_MAX_CHANNEL_NUM) {
510 dev_err(&pdev->dev, "Channel id is out of range: %d\n", pc->channel_id);
511 ret = -EINVAL;
512 goto err_pclk;
513 }
514
515 if (IS_ENABLED(CONFIG_PWM_ROCKCHIP_ONESHOT)) {
516 pc->irq = platform_get_irq(pdev, 0);
517 if (pc->irq < 0) {
518 dev_err(&pdev->dev, "Get oneshot mode irq failed\n");
519 ret = pc->irq;
520 goto err_pclk;
521 }
522
523 ret = devm_request_irq(&pdev->dev, pc->irq, rockchip_pwm_oneshot_irq,
524 IRQF_NO_SUSPEND | IRQF_SHARED,
525 "rk_pwm_oneshot_irq", pc);
526 if (ret) {
527 dev_err(&pdev->dev, "Claim oneshot IRQ failed\n");
528 goto err_pclk;
529 }
530 }
531
532 pc->pinctrl = devm_pinctrl_get(&pdev->dev);
533 if (IS_ERR(pc->pinctrl)) {
534 dev_err(&pdev->dev, "Get pinctrl failed!\n");
535 ret = PTR_ERR(pc->pinctrl);
536 goto err_pclk;
537 }
538
539 pc->active_state = pinctrl_lookup_state(pc->pinctrl, "active");
540 if (IS_ERR(pc->active_state)) {
541 dev_err(&pdev->dev, "No active pinctrl state\n");
542 ret = PTR_ERR(pc->active_state);
543 goto err_pclk;
544 }
545
546 platform_set_drvdata(pdev, pc);
547
548 pc->data = id->data;
549 pc->chip.dev = &pdev->dev;
550 pc->chip.ops = &rockchip_pwm_ops;
551 pc->chip.base = of_alias_get_id(pdev->dev.of_node, "pwm");
552 pc->chip.npwm = 1;
553 pc->clk_rate = clk_get_rate(pc->clk);
554
555 if (pc->data->supports_polarity) {
556 pc->chip.of_xlate = of_pwm_xlate_with_flags;
557 pc->chip.of_pwm_n_cells = 3;
558 }
559
560 enable_conf = pc->data->enable_conf;
561 ctrl = readl_relaxed(pc->base + pc->data->regs.ctrl);
562 enabled = (ctrl & enable_conf) == enable_conf;
563
564 pc->center_aligned =
565 device_property_read_bool(&pdev->dev, "center-aligned");
566
567 ret = pwmchip_add(&pc->chip);
568 if (ret < 0) {
569 dev_err(&pdev->dev, "pwmchip_add() failed: %d\n", ret);
570 goto err_pclk;
571 }
572
573 /* Keep the PWM clk enabled if the PWM appears to be up and running. */
574 if (!enabled)
575 clk_disable(pc->clk);
576
577 clk_disable(pc->pclk);
578
579 return 0;
580
581 err_pclk:
582 clk_disable_unprepare(pc->pclk);
583 err_clk:
584 clk_disable_unprepare(pc->clk);
585
586 return ret;
587 }
588
rockchip_pwm_remove(struct platform_device * pdev)589 static int rockchip_pwm_remove(struct platform_device *pdev)
590 {
591 struct rockchip_pwm_chip *pc = platform_get_drvdata(pdev);
592 struct pwm_state state;
593 u32 val;
594
595 /*
596 * For oneshot mode, it is needed to wait for bit PWM_ENABLE
597 * to 0, which is automatic if all periods have been sent.
598 */
599 pwm_get_state(&pc->chip.pwms[0], &state);
600 if (state.enabled) {
601 if (pc->oneshot_en) {
602 if (readl_poll_timeout(pc->base + pc->data->regs.ctrl,
603 val, !(val & PWM_ENABLE), 1000, 10 * 1000))
604 dev_err(&pdev->dev, "Wait for oneshot to complete failed\n");
605 } else {
606 state.enabled = false;
607 pwm_apply_state(&pc->chip.pwms[0], &state);
608 }
609 }
610
611 if (pc->oneshot_en)
612 clk_disable(pc->pclk);
613 clk_unprepare(pc->pclk);
614 clk_unprepare(pc->clk);
615
616 return pwmchip_remove(&pc->chip);
617 }
618
619 static struct platform_driver rockchip_pwm_driver = {
620 .driver = {
621 .name = "rockchip-pwm",
622 .of_match_table = rockchip_pwm_dt_ids,
623 },
624 .probe = rockchip_pwm_probe,
625 .remove = rockchip_pwm_remove,
626 };
627 #ifdef CONFIG_ROCKCHIP_THUNDER_BOOT
rockchip_pwm_driver_init(void)628 static int __init rockchip_pwm_driver_init(void)
629 {
630 return platform_driver_register(&rockchip_pwm_driver);
631 }
632 subsys_initcall(rockchip_pwm_driver_init);
633
rockchip_pwm_driver_exit(void)634 static void __exit rockchip_pwm_driver_exit(void)
635 {
636 platform_driver_unregister(&rockchip_pwm_driver);
637 }
638 module_exit(rockchip_pwm_driver_exit);
639 #else
640 module_platform_driver(rockchip_pwm_driver);
641 #endif
642
643 MODULE_AUTHOR("Beniamino Galvani <b.galvani@gmail.com>");
644 MODULE_DESCRIPTION("Rockchip SoC PWM driver");
645 MODULE_LICENSE("GPL v2");
646