2 * R-Car PWM Timer driver
4 * Copyright (C) 2015 Renesas Electronics Corporation
6 * This is free software; you can redistribute it and/or modify
7 * it under the terms of version 2 of the GNU General Public License as
8 * published by the Free Software Foundation.
11 #include <linux/clk.h>
12 #include <linux/err.h>
14 #include <linux/module.h>
16 #include <linux/platform_device.h>
17 #include <linux/pm_runtime.h>
18 #include <linux/pwm.h>
19 #include <linux/slab.h>
21 #define RCAR_PWM_MAX_DIVISION 24
22 #define RCAR_PWM_MAX_CYCLE 1023
24 #define RCAR_PWMCR 0x00
25 #define RCAR_PWMCR_CC0_MASK 0x000f0000
26 #define RCAR_PWMCR_CC0_SHIFT 16
27 #define RCAR_PWMCR_CCMD BIT(15)
28 #define RCAR_PWMCR_SYNC BIT(11)
29 #define RCAR_PWMCR_SS0 BIT(4)
30 #define RCAR_PWMCR_EN0 BIT(0)
32 #define RCAR_PWMCNT 0x04
33 #define RCAR_PWMCNT_CYC0_MASK 0x03ff0000
34 #define RCAR_PWMCNT_CYC0_SHIFT 16
35 #define RCAR_PWMCNT_PH0_MASK 0x000003ff
36 #define RCAR_PWMCNT_PH0_SHIFT 0
38 struct rcar_pwm_chip
{
44 static inline struct rcar_pwm_chip
*to_rcar_pwm_chip(struct pwm_chip
*chip
)
46 return container_of(chip
, struct rcar_pwm_chip
, chip
);
49 static void rcar_pwm_write(struct rcar_pwm_chip
*rp
, u32 data
,
52 writel(data
, rp
->base
+ offset
);
55 static u32
rcar_pwm_read(struct rcar_pwm_chip
*rp
, unsigned int offset
)
57 return readl(rp
->base
+ offset
);
60 static void rcar_pwm_update(struct rcar_pwm_chip
*rp
, u32 mask
, u32 data
,
65 value
= rcar_pwm_read(rp
, offset
);
68 rcar_pwm_write(rp
, value
, offset
);
71 static int rcar_pwm_get_clock_division(struct rcar_pwm_chip
*rp
, int period_ns
)
73 unsigned long clk_rate
= clk_get_rate(rp
->clk
);
74 unsigned long long max
; /* max cycle / nanoseconds */
80 for (div
= 0; div
<= RCAR_PWM_MAX_DIVISION
; div
++) {
81 max
= (unsigned long long)NSEC_PER_SEC
* RCAR_PWM_MAX_CYCLE
*
83 do_div(max
, clk_rate
);
88 return (div
<= RCAR_PWM_MAX_DIVISION
) ? div
: -ERANGE
;
91 static void rcar_pwm_set_clock_control(struct rcar_pwm_chip
*rp
,
96 value
= rcar_pwm_read(rp
, RCAR_PWMCR
);
97 value
&= ~(RCAR_PWMCR_CCMD
| RCAR_PWMCR_CC0_MASK
);
100 value
|= RCAR_PWMCR_CCMD
;
104 value
|= div
<< RCAR_PWMCR_CC0_SHIFT
;
105 rcar_pwm_write(rp
, value
, RCAR_PWMCR
);
108 static int rcar_pwm_set_counter(struct rcar_pwm_chip
*rp
, int div
, int duty_ns
,
111 unsigned long long one_cycle
, tmp
; /* 0.01 nanoseconds */
112 unsigned long clk_rate
= clk_get_rate(rp
->clk
);
115 one_cycle
= (unsigned long long)NSEC_PER_SEC
* 100ULL * (1 << div
);
116 do_div(one_cycle
, clk_rate
);
118 tmp
= period_ns
* 100ULL;
119 do_div(tmp
, one_cycle
);
120 cyc
= (tmp
<< RCAR_PWMCNT_CYC0_SHIFT
) & RCAR_PWMCNT_CYC0_MASK
;
122 tmp
= duty_ns
* 100ULL;
123 do_div(tmp
, one_cycle
);
124 ph
= tmp
& RCAR_PWMCNT_PH0_MASK
;
126 /* Avoid prohibited setting */
127 if (cyc
== 0 || ph
== 0)
130 rcar_pwm_write(rp
, cyc
| ph
, RCAR_PWMCNT
);
135 static int rcar_pwm_request(struct pwm_chip
*chip
, struct pwm_device
*pwm
)
137 struct rcar_pwm_chip
*rp
= to_rcar_pwm_chip(chip
);
139 return clk_prepare_enable(rp
->clk
);
142 static void rcar_pwm_free(struct pwm_chip
*chip
, struct pwm_device
*pwm
)
144 struct rcar_pwm_chip
*rp
= to_rcar_pwm_chip(chip
);
146 clk_disable_unprepare(rp
->clk
);
149 static int rcar_pwm_config(struct pwm_chip
*chip
, struct pwm_device
*pwm
,
150 int duty_ns
, int period_ns
)
152 struct rcar_pwm_chip
*rp
= to_rcar_pwm_chip(chip
);
155 div
= rcar_pwm_get_clock_division(rp
, period_ns
);
159 /* Let the core driver set pwm->period if disabled and duty_ns == 0 */
160 if (!test_bit(PWMF_ENABLED
, &pwm
->flags
) && !duty_ns
)
163 rcar_pwm_update(rp
, RCAR_PWMCR_SYNC
, RCAR_PWMCR_SYNC
, RCAR_PWMCR
);
165 ret
= rcar_pwm_set_counter(rp
, div
, duty_ns
, period_ns
);
167 rcar_pwm_set_clock_control(rp
, div
);
169 /* The SYNC should be set to 0 even if rcar_pwm_set_counter failed */
170 rcar_pwm_update(rp
, RCAR_PWMCR_SYNC
, 0, RCAR_PWMCR
);
175 static int rcar_pwm_enable(struct pwm_chip
*chip
, struct pwm_device
*pwm
)
177 struct rcar_pwm_chip
*rp
= to_rcar_pwm_chip(chip
);
180 /* Don't enable the PWM device if CYC0 or PH0 is 0 */
181 value
= rcar_pwm_read(rp
, RCAR_PWMCNT
);
182 if ((value
& RCAR_PWMCNT_CYC0_MASK
) == 0 ||
183 (value
& RCAR_PWMCNT_PH0_MASK
) == 0)
186 rcar_pwm_update(rp
, RCAR_PWMCR_EN0
, RCAR_PWMCR_EN0
, RCAR_PWMCR
);
191 static void rcar_pwm_disable(struct pwm_chip
*chip
, struct pwm_device
*pwm
)
193 struct rcar_pwm_chip
*rp
= to_rcar_pwm_chip(chip
);
195 rcar_pwm_update(rp
, RCAR_PWMCR_EN0
, 0, RCAR_PWMCR
);
198 static const struct pwm_ops rcar_pwm_ops
= {
199 .request
= rcar_pwm_request
,
200 .free
= rcar_pwm_free
,
201 .config
= rcar_pwm_config
,
202 .enable
= rcar_pwm_enable
,
203 .disable
= rcar_pwm_disable
,
204 .owner
= THIS_MODULE
,
207 static int rcar_pwm_probe(struct platform_device
*pdev
)
209 struct rcar_pwm_chip
*rcar_pwm
;
210 struct resource
*res
;
213 rcar_pwm
= devm_kzalloc(&pdev
->dev
, sizeof(*rcar_pwm
), GFP_KERNEL
);
214 if (rcar_pwm
== NULL
)
217 res
= platform_get_resource(pdev
, IORESOURCE_MEM
, 0);
218 rcar_pwm
->base
= devm_ioremap_resource(&pdev
->dev
, res
);
219 if (IS_ERR(rcar_pwm
->base
))
220 return PTR_ERR(rcar_pwm
->base
);
222 rcar_pwm
->clk
= devm_clk_get(&pdev
->dev
, NULL
);
223 if (IS_ERR(rcar_pwm
->clk
)) {
224 dev_err(&pdev
->dev
, "cannot get clock\n");
225 return PTR_ERR(rcar_pwm
->clk
);
228 platform_set_drvdata(pdev
, rcar_pwm
);
230 rcar_pwm
->chip
.dev
= &pdev
->dev
;
231 rcar_pwm
->chip
.ops
= &rcar_pwm_ops
;
232 rcar_pwm
->chip
.base
= -1;
233 rcar_pwm
->chip
.npwm
= 1;
235 ret
= pwmchip_add(&rcar_pwm
->chip
);
237 dev_err(&pdev
->dev
, "failed to register PWM chip: %d\n", ret
);
241 pm_runtime_enable(&pdev
->dev
);
246 static int rcar_pwm_remove(struct platform_device
*pdev
)
248 struct rcar_pwm_chip
*rcar_pwm
= platform_get_drvdata(pdev
);
250 pm_runtime_disable(&pdev
->dev
);
252 return pwmchip_remove(&rcar_pwm
->chip
);
255 static const struct of_device_id rcar_pwm_of_table
[] = {
256 { .compatible
= "renesas,pwm-rcar", },
259 MODULE_DEVICE_TABLE(of
, rcar_pwm_of_table
);
261 static struct platform_driver rcar_pwm_driver
= {
262 .probe
= rcar_pwm_probe
,
263 .remove
= rcar_pwm_remove
,
266 .of_match_table
= of_match_ptr(rcar_pwm_of_table
),
269 module_platform_driver(rcar_pwm_driver
);
271 MODULE_AUTHOR("Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>");
272 MODULE_DESCRIPTION("Renesas PWM Timer Driver");
273 MODULE_LICENSE("GPL v2");
274 MODULE_ALIAS("platform:pwm-rcar");