2 * PWM driver for Rockchip SoCs
4 * Copyright (C) 2014 Beniamino Galvani <b.galvani@gmail.com>
5 * Copyright (C) 2014 ROCKCHIP, Inc.
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * version 2 as published by the Free Software Foundation.
12 #include <linux/clk.h>
14 #include <linux/module.h>
16 #include <linux/of_device.h>
17 #include <linux/platform_device.h>
18 #include <linux/pwm.h>
19 #include <linux/time.h>
21 #define PWM_CTRL_TIMER_EN (1 << 0)
22 #define PWM_CTRL_OUTPUT_EN (1 << 3)
24 #define PWM_ENABLE (1 << 0)
25 #define PWM_CONTINUOUS (1 << 1)
26 #define PWM_DUTY_POSITIVE (1 << 3)
27 #define PWM_DUTY_NEGATIVE (0 << 3)
28 #define PWM_INACTIVE_NEGATIVE (0 << 4)
29 #define PWM_INACTIVE_POSITIVE (1 << 4)
30 #define PWM_OUTPUT_LEFT (0 << 5)
31 #define PWM_LP_DISABLE (0 << 8)
33 struct rockchip_pwm_chip
{
36 const struct rockchip_pwm_data
*data
;
40 struct rockchip_pwm_regs
{
47 struct rockchip_pwm_data
{
48 struct rockchip_pwm_regs regs
;
49 unsigned int prescaler
;
50 bool supports_polarity
;
51 const struct pwm_ops
*ops
;
53 void (*set_enable
)(struct pwm_chip
*chip
,
54 struct pwm_device
*pwm
, bool enable
,
55 enum pwm_polarity polarity
);
56 void (*get_state
)(struct pwm_chip
*chip
, struct pwm_device
*pwm
,
57 struct pwm_state
*state
);
60 static inline struct rockchip_pwm_chip
*to_rockchip_pwm_chip(struct pwm_chip
*c
)
62 return container_of(c
, struct rockchip_pwm_chip
, chip
);
65 static void rockchip_pwm_set_enable_v1(struct pwm_chip
*chip
,
66 struct pwm_device
*pwm
, bool enable
,
67 enum pwm_polarity polarity
)
69 struct rockchip_pwm_chip
*pc
= to_rockchip_pwm_chip(chip
);
70 u32 enable_conf
= PWM_CTRL_OUTPUT_EN
| PWM_CTRL_TIMER_EN
;
73 val
= readl_relaxed(pc
->base
+ pc
->data
->regs
.ctrl
);
80 writel_relaxed(val
, pc
->base
+ pc
->data
->regs
.ctrl
);
83 static void rockchip_pwm_get_state_v1(struct pwm_chip
*chip
,
84 struct pwm_device
*pwm
,
85 struct pwm_state
*state
)
87 struct rockchip_pwm_chip
*pc
= to_rockchip_pwm_chip(chip
);
88 u32 enable_conf
= PWM_CTRL_OUTPUT_EN
| PWM_CTRL_TIMER_EN
;
91 val
= readl_relaxed(pc
->base
+ pc
->data
->regs
.ctrl
);
92 if ((val
& enable_conf
) == enable_conf
)
93 state
->enabled
= true;
96 static void rockchip_pwm_set_enable_v2(struct pwm_chip
*chip
,
97 struct pwm_device
*pwm
, bool enable
,
98 enum pwm_polarity polarity
)
100 struct rockchip_pwm_chip
*pc
= to_rockchip_pwm_chip(chip
);
101 u32 enable_conf
= PWM_OUTPUT_LEFT
| PWM_LP_DISABLE
| PWM_ENABLE
|
105 if (polarity
== PWM_POLARITY_INVERSED
)
106 enable_conf
|= PWM_DUTY_NEGATIVE
| PWM_INACTIVE_POSITIVE
;
108 enable_conf
|= PWM_DUTY_POSITIVE
| PWM_INACTIVE_NEGATIVE
;
110 val
= readl_relaxed(pc
->base
+ pc
->data
->regs
.ctrl
);
117 writel_relaxed(val
, pc
->base
+ pc
->data
->regs
.ctrl
);
120 static void rockchip_pwm_get_state_v2(struct pwm_chip
*chip
,
121 struct pwm_device
*pwm
,
122 struct pwm_state
*state
)
124 struct rockchip_pwm_chip
*pc
= to_rockchip_pwm_chip(chip
);
125 u32 enable_conf
= PWM_OUTPUT_LEFT
| PWM_LP_DISABLE
| PWM_ENABLE
|
129 val
= readl_relaxed(pc
->base
+ pc
->data
->regs
.ctrl
);
130 if ((val
& enable_conf
) != enable_conf
)
133 state
->enabled
= true;
135 if (!(val
& PWM_DUTY_POSITIVE
))
136 state
->polarity
= PWM_POLARITY_INVERSED
;
139 static void rockchip_pwm_get_state(struct pwm_chip
*chip
,
140 struct pwm_device
*pwm
,
141 struct pwm_state
*state
)
143 struct rockchip_pwm_chip
*pc
= to_rockchip_pwm_chip(chip
);
144 unsigned long clk_rate
;
148 ret
= clk_enable(pc
->clk
);
152 clk_rate
= clk_get_rate(pc
->clk
);
154 tmp
= readl_relaxed(pc
->base
+ pc
->data
->regs
.period
);
155 tmp
*= pc
->data
->prescaler
* NSEC_PER_SEC
;
156 state
->period
= DIV_ROUND_CLOSEST_ULL(tmp
, clk_rate
);
158 tmp
= readl_relaxed(pc
->base
+ pc
->data
->regs
.duty
);
159 tmp
*= pc
->data
->prescaler
* NSEC_PER_SEC
;
160 state
->duty_cycle
= DIV_ROUND_CLOSEST_ULL(tmp
, clk_rate
);
162 pc
->data
->get_state(chip
, pwm
, state
);
164 clk_disable(pc
->clk
);
167 static int rockchip_pwm_config(struct pwm_chip
*chip
, struct pwm_device
*pwm
,
168 int duty_ns
, int period_ns
)
170 struct rockchip_pwm_chip
*pc
= to_rockchip_pwm_chip(chip
);
171 unsigned long period
, duty
;
174 clk_rate
= clk_get_rate(pc
->clk
);
177 * Since period and duty cycle registers have a width of 32
178 * bits, every possible input period can be obtained using the
179 * default prescaler value for all practical clock rate values.
181 div
= clk_rate
* period_ns
;
182 period
= DIV_ROUND_CLOSEST_ULL(div
,
183 pc
->data
->prescaler
* NSEC_PER_SEC
);
185 div
= clk_rate
* duty_ns
;
186 duty
= DIV_ROUND_CLOSEST_ULL(div
, pc
->data
->prescaler
* NSEC_PER_SEC
);
188 writel(period
, pc
->base
+ pc
->data
->regs
.period
);
189 writel(duty
, pc
->base
+ pc
->data
->regs
.duty
);
194 static int rockchip_pwm_enable(struct pwm_chip
*chip
,
195 struct pwm_device
*pwm
,
197 enum pwm_polarity polarity
)
199 struct rockchip_pwm_chip
*pc
= to_rockchip_pwm_chip(chip
);
203 ret
= clk_enable(pc
->clk
);
208 pc
->data
->set_enable(chip
, pwm
, enable
, polarity
);
211 clk_disable(pc
->clk
);
216 static int rockchip_pwm_apply(struct pwm_chip
*chip
, struct pwm_device
*pwm
,
217 struct pwm_state
*state
)
219 struct rockchip_pwm_chip
*pc
= to_rockchip_pwm_chip(chip
);
220 struct pwm_state curstate
;
224 pwm_get_state(pwm
, &curstate
);
225 enabled
= curstate
.enabled
;
227 ret
= clk_enable(pc
->clk
);
231 if (state
->polarity
!= curstate
.polarity
&& enabled
) {
232 ret
= rockchip_pwm_enable(chip
, pwm
, false, state
->polarity
);
238 ret
= rockchip_pwm_config(chip
, pwm
, state
->duty_cycle
, state
->period
);
240 if (enabled
!= curstate
.enabled
)
241 rockchip_pwm_enable(chip
, pwm
, !enabled
,
246 if (state
->enabled
!= enabled
) {
247 ret
= rockchip_pwm_enable(chip
, pwm
, state
->enabled
,
254 * Update the state with the real hardware, which can differ a bit
255 * because of period/duty_cycle approximation.
257 rockchip_pwm_get_state(chip
, pwm
, state
);
260 clk_disable(pc
->clk
);
265 static const struct pwm_ops rockchip_pwm_ops_v1
= {
266 .get_state
= rockchip_pwm_get_state
,
267 .apply
= rockchip_pwm_apply
,
268 .owner
= THIS_MODULE
,
271 static const struct pwm_ops rockchip_pwm_ops_v2
= {
272 .get_state
= rockchip_pwm_get_state
,
273 .apply
= rockchip_pwm_apply
,
274 .owner
= THIS_MODULE
,
277 static const struct rockchip_pwm_data pwm_data_v1
= {
285 .ops
= &rockchip_pwm_ops_v1
,
286 .set_enable
= rockchip_pwm_set_enable_v1
,
287 .get_state
= rockchip_pwm_get_state_v1
,
290 static const struct rockchip_pwm_data pwm_data_v2
= {
298 .supports_polarity
= true,
299 .ops
= &rockchip_pwm_ops_v2
,
300 .set_enable
= rockchip_pwm_set_enable_v2
,
301 .get_state
= rockchip_pwm_get_state_v2
,
304 static const struct rockchip_pwm_data pwm_data_vop
= {
312 .supports_polarity
= true,
313 .ops
= &rockchip_pwm_ops_v2
,
314 .set_enable
= rockchip_pwm_set_enable_v2
,
315 .get_state
= rockchip_pwm_get_state_v2
,
318 static const struct of_device_id rockchip_pwm_dt_ids
[] = {
319 { .compatible
= "rockchip,rk2928-pwm", .data
= &pwm_data_v1
},
320 { .compatible
= "rockchip,rk3288-pwm", .data
= &pwm_data_v2
},
321 { .compatible
= "rockchip,vop-pwm", .data
= &pwm_data_vop
},
324 MODULE_DEVICE_TABLE(of
, rockchip_pwm_dt_ids
);
326 static int rockchip_pwm_probe(struct platform_device
*pdev
)
328 const struct of_device_id
*id
;
329 struct rockchip_pwm_chip
*pc
;
333 id
= of_match_device(rockchip_pwm_dt_ids
, &pdev
->dev
);
337 pc
= devm_kzalloc(&pdev
->dev
, sizeof(*pc
), GFP_KERNEL
);
341 r
= platform_get_resource(pdev
, IORESOURCE_MEM
, 0);
342 pc
->base
= devm_ioremap_resource(&pdev
->dev
, r
);
343 if (IS_ERR(pc
->base
))
344 return PTR_ERR(pc
->base
);
346 pc
->clk
= devm_clk_get(&pdev
->dev
, NULL
);
348 return PTR_ERR(pc
->clk
);
350 ret
= clk_prepare_enable(pc
->clk
);
354 platform_set_drvdata(pdev
, pc
);
357 pc
->chip
.dev
= &pdev
->dev
;
358 pc
->chip
.ops
= pc
->data
->ops
;
362 if (pc
->data
->supports_polarity
) {
363 pc
->chip
.of_xlate
= of_pwm_xlate_with_flags
;
364 pc
->chip
.of_pwm_n_cells
= 3;
367 ret
= pwmchip_add(&pc
->chip
);
369 clk_unprepare(pc
->clk
);
370 dev_err(&pdev
->dev
, "pwmchip_add() failed: %d\n", ret
);
373 /* Keep the PWM clk enabled if the PWM appears to be up and running. */
374 if (!pwm_is_enabled(pc
->chip
.pwms
))
375 clk_disable(pc
->clk
);
380 static int rockchip_pwm_remove(struct platform_device
*pdev
)
382 struct rockchip_pwm_chip
*pc
= platform_get_drvdata(pdev
);
385 * Disable the PWM clk before unpreparing it if the PWM device is still
386 * running. This should only happen when the last PWM user left it
387 * enabled, or when nobody requested a PWM that was previously enabled
390 * FIXME: Maybe the core should disable all PWM devices in
391 * pwmchip_remove(). In this case we'd only have to call
392 * clk_unprepare() after pwmchip_remove().
395 if (pwm_is_enabled(pc
->chip
.pwms
))
396 clk_disable(pc
->clk
);
398 clk_unprepare(pc
->clk
);
400 return pwmchip_remove(&pc
->chip
);
403 static struct platform_driver rockchip_pwm_driver
= {
405 .name
= "rockchip-pwm",
406 .of_match_table
= rockchip_pwm_dt_ids
,
408 .probe
= rockchip_pwm_probe
,
409 .remove
= rockchip_pwm_remove
,
411 module_platform_driver(rockchip_pwm_driver
);
413 MODULE_AUTHOR("Beniamino Galvani <b.galvani@gmail.com>");
414 MODULE_DESCRIPTION("Rockchip SoC PWM driver");
415 MODULE_LICENSE("GPL v2");