2 * Copyright (C) Overkiz SAS 2012
4 * Author: Boris BREZILLON <b.brezillon@overkiz.com>
5 * License terms: GNU General Public License (GPL) version 2
8 #include <linux/module.h>
9 #include <linux/init.h>
10 #include <linux/clocksource.h>
11 #include <linux/clockchips.h>
12 #include <linux/interrupt.h>
13 #include <linux/irq.h>
15 #include <linux/clk.h>
16 #include <linux/err.h>
17 #include <linux/ioport.h>
19 #include <linux/platform_device.h>
20 #include <linux/atmel_tc.h>
21 #include <linux/pwm.h>
22 #include <linux/of_device.h>
23 #include <linux/slab.h>
27 #define ATMEL_TC_ACMR_MASK (ATMEL_TC_ACPA | ATMEL_TC_ACPC | \
28 ATMEL_TC_AEEVT | ATMEL_TC_ASWTRG)
30 #define ATMEL_TC_BCMR_MASK (ATMEL_TC_BCPB | ATMEL_TC_BCPC | \
31 ATMEL_TC_BEEVT | ATMEL_TC_BSWTRG)
33 struct atmel_tcb_pwm_device
{
34 enum pwm_polarity polarity
; /* PWM polarity */
35 unsigned div
; /* PWM clock divider */
36 unsigned duty
; /* PWM duty expressed in clk cycles */
37 unsigned period
; /* PWM period expressed in clk cycles */
40 struct atmel_tcb_pwm_chip
{
44 struct atmel_tcb_pwm_device
*pwms
[NPWM
];
47 static inline struct atmel_tcb_pwm_chip
*to_tcb_chip(struct pwm_chip
*chip
)
49 return container_of(chip
, struct atmel_tcb_pwm_chip
, chip
);
52 static int atmel_tcb_pwm_set_polarity(struct pwm_chip
*chip
,
53 struct pwm_device
*pwm
,
54 enum pwm_polarity polarity
)
56 struct atmel_tcb_pwm_device
*tcbpwm
= pwm_get_chip_data(pwm
);
58 tcbpwm
->polarity
= polarity
;
63 static int atmel_tcb_pwm_request(struct pwm_chip
*chip
,
64 struct pwm_device
*pwm
)
66 struct atmel_tcb_pwm_chip
*tcbpwmc
= to_tcb_chip(chip
);
67 struct atmel_tcb_pwm_device
*tcbpwm
;
68 struct atmel_tc
*tc
= tcbpwmc
->tc
;
69 void __iomem
*regs
= tc
->regs
;
70 unsigned group
= pwm
->hwpwm
/ 2;
71 unsigned index
= pwm
->hwpwm
% 2;
75 tcbpwm
= devm_kzalloc(chip
->dev
, sizeof(*tcbpwm
), GFP_KERNEL
);
79 ret
= clk_prepare_enable(tc
->clk
[group
]);
81 devm_kfree(chip
->dev
, tcbpwm
);
85 pwm_set_chip_data(pwm
, tcbpwm
);
86 tcbpwm
->polarity
= PWM_POLARITY_NORMAL
;
91 spin_lock(&tcbpwmc
->lock
);
92 cmr
= __raw_readl(regs
+ ATMEL_TC_REG(group
, CMR
));
94 * Get init config from Timer Counter registers if
95 * Timer Counter is already configured as a PWM generator.
97 if (cmr
& ATMEL_TC_WAVE
) {
100 __raw_readl(regs
+ ATMEL_TC_REG(group
, RA
));
103 __raw_readl(regs
+ ATMEL_TC_REG(group
, RB
));
105 tcbpwm
->div
= cmr
& ATMEL_TC_TCCLKS
;
106 tcbpwm
->period
= __raw_readl(regs
+ ATMEL_TC_REG(group
, RC
));
107 cmr
&= (ATMEL_TC_TCCLKS
| ATMEL_TC_ACMR_MASK
|
112 cmr
|= ATMEL_TC_WAVE
| ATMEL_TC_WAVESEL_UP_AUTO
| ATMEL_TC_EEVT_XC0
;
113 __raw_writel(cmr
, regs
+ ATMEL_TC_REG(group
, CMR
));
114 spin_unlock(&tcbpwmc
->lock
);
116 tcbpwmc
->pwms
[pwm
->hwpwm
] = tcbpwm
;
121 static void atmel_tcb_pwm_free(struct pwm_chip
*chip
, struct pwm_device
*pwm
)
123 struct atmel_tcb_pwm_chip
*tcbpwmc
= to_tcb_chip(chip
);
124 struct atmel_tcb_pwm_device
*tcbpwm
= pwm_get_chip_data(pwm
);
125 struct atmel_tc
*tc
= tcbpwmc
->tc
;
127 clk_disable_unprepare(tc
->clk
[pwm
->hwpwm
/ 2]);
128 tcbpwmc
->pwms
[pwm
->hwpwm
] = NULL
;
129 devm_kfree(chip
->dev
, tcbpwm
);
132 static void atmel_tcb_pwm_disable(struct pwm_chip
*chip
, struct pwm_device
*pwm
)
134 struct atmel_tcb_pwm_chip
*tcbpwmc
= to_tcb_chip(chip
);
135 struct atmel_tcb_pwm_device
*tcbpwm
= pwm_get_chip_data(pwm
);
136 struct atmel_tc
*tc
= tcbpwmc
->tc
;
137 void __iomem
*regs
= tc
->regs
;
138 unsigned group
= pwm
->hwpwm
/ 2;
139 unsigned index
= pwm
->hwpwm
% 2;
141 enum pwm_polarity polarity
= tcbpwm
->polarity
;
144 * If duty is 0 the timer will be stopped and we have to
145 * configure the output correctly on software trigger:
146 * - set output to high if PWM_POLARITY_INVERSED
147 * - set output to low if PWM_POLARITY_NORMAL
149 * This is why we're reverting polarity in this case.
151 if (tcbpwm
->duty
== 0)
152 polarity
= !polarity
;
154 spin_lock(&tcbpwmc
->lock
);
155 cmr
= __raw_readl(regs
+ ATMEL_TC_REG(group
, CMR
));
157 /* flush old setting and set the new one */
159 cmr
&= ~ATMEL_TC_ACMR_MASK
;
160 if (polarity
== PWM_POLARITY_INVERSED
)
161 cmr
|= ATMEL_TC_ASWTRG_CLEAR
;
163 cmr
|= ATMEL_TC_ASWTRG_SET
;
165 cmr
&= ~ATMEL_TC_BCMR_MASK
;
166 if (polarity
== PWM_POLARITY_INVERSED
)
167 cmr
|= ATMEL_TC_BSWTRG_CLEAR
;
169 cmr
|= ATMEL_TC_BSWTRG_SET
;
172 __raw_writel(cmr
, regs
+ ATMEL_TC_REG(group
, CMR
));
175 * Use software trigger to apply the new setting.
176 * If both PWM devices in this group are disabled we stop the clock.
178 if (!(cmr
& (ATMEL_TC_ACPC
| ATMEL_TC_BCPC
)))
179 __raw_writel(ATMEL_TC_SWTRG
| ATMEL_TC_CLKDIS
,
180 regs
+ ATMEL_TC_REG(group
, CCR
));
182 __raw_writel(ATMEL_TC_SWTRG
, regs
+
183 ATMEL_TC_REG(group
, CCR
));
185 spin_unlock(&tcbpwmc
->lock
);
188 static int atmel_tcb_pwm_enable(struct pwm_chip
*chip
, struct pwm_device
*pwm
)
190 struct atmel_tcb_pwm_chip
*tcbpwmc
= to_tcb_chip(chip
);
191 struct atmel_tcb_pwm_device
*tcbpwm
= pwm_get_chip_data(pwm
);
192 struct atmel_tc
*tc
= tcbpwmc
->tc
;
193 void __iomem
*regs
= tc
->regs
;
194 unsigned group
= pwm
->hwpwm
/ 2;
195 unsigned index
= pwm
->hwpwm
% 2;
197 enum pwm_polarity polarity
= tcbpwm
->polarity
;
200 * If duty is 0 the timer will be stopped and we have to
201 * configure the output correctly on software trigger:
202 * - set output to high if PWM_POLARITY_INVERSED
203 * - set output to low if PWM_POLARITY_NORMAL
205 * This is why we're reverting polarity in this case.
207 if (tcbpwm
->duty
== 0)
208 polarity
= !polarity
;
210 spin_lock(&tcbpwmc
->lock
);
211 cmr
= __raw_readl(regs
+ ATMEL_TC_REG(group
, CMR
));
213 /* flush old setting and set the new one */
214 cmr
&= ~ATMEL_TC_TCCLKS
;
217 cmr
&= ~ATMEL_TC_ACMR_MASK
;
219 /* Set CMR flags according to given polarity */
220 if (polarity
== PWM_POLARITY_INVERSED
)
221 cmr
|= ATMEL_TC_ASWTRG_CLEAR
;
223 cmr
|= ATMEL_TC_ASWTRG_SET
;
225 cmr
&= ~ATMEL_TC_BCMR_MASK
;
226 if (polarity
== PWM_POLARITY_INVERSED
)
227 cmr
|= ATMEL_TC_BSWTRG_CLEAR
;
229 cmr
|= ATMEL_TC_BSWTRG_SET
;
233 * If duty is 0 or equal to period there's no need to register
234 * a specific action on RA/RB and RC compare.
235 * The output will be configured on software trigger and keep
236 * this config till next config call.
238 if (tcbpwm
->duty
!= tcbpwm
->period
&& tcbpwm
->duty
> 0) {
240 if (polarity
== PWM_POLARITY_INVERSED
)
241 cmr
|= ATMEL_TC_ACPA_SET
| ATMEL_TC_ACPC_CLEAR
;
243 cmr
|= ATMEL_TC_ACPA_CLEAR
| ATMEL_TC_ACPC_SET
;
245 if (polarity
== PWM_POLARITY_INVERSED
)
246 cmr
|= ATMEL_TC_BCPB_SET
| ATMEL_TC_BCPC_CLEAR
;
248 cmr
|= ATMEL_TC_BCPB_CLEAR
| ATMEL_TC_BCPC_SET
;
252 cmr
|= (tcbpwm
->div
& ATMEL_TC_TCCLKS
);
254 __raw_writel(cmr
, regs
+ ATMEL_TC_REG(group
, CMR
));
257 __raw_writel(tcbpwm
->duty
, regs
+ ATMEL_TC_REG(group
, RA
));
259 __raw_writel(tcbpwm
->duty
, regs
+ ATMEL_TC_REG(group
, RB
));
261 __raw_writel(tcbpwm
->period
, regs
+ ATMEL_TC_REG(group
, RC
));
263 /* Use software trigger to apply the new setting */
264 __raw_writel(ATMEL_TC_CLKEN
| ATMEL_TC_SWTRG
,
265 regs
+ ATMEL_TC_REG(group
, CCR
));
266 spin_unlock(&tcbpwmc
->lock
);
270 static int atmel_tcb_pwm_config(struct pwm_chip
*chip
, struct pwm_device
*pwm
,
271 int duty_ns
, int period_ns
)
273 struct atmel_tcb_pwm_chip
*tcbpwmc
= to_tcb_chip(chip
);
274 struct atmel_tcb_pwm_device
*tcbpwm
= pwm_get_chip_data(pwm
);
275 unsigned group
= pwm
->hwpwm
/ 2;
276 unsigned index
= pwm
->hwpwm
% 2;
277 struct atmel_tcb_pwm_device
*atcbpwm
= NULL
;
278 struct atmel_tc
*tc
= tcbpwmc
->tc
;
283 unsigned rate
= clk_get_rate(tc
->clk
[group
]);
284 unsigned long long min
;
285 unsigned long long max
;
288 * Find best clk divisor:
289 * the smallest divisor which can fulfill the period_ns requirements.
291 for (i
= 0; i
< 5; ++i
) {
292 if (atmel_tc_divisors
[i
] == 0) {
296 min
= div_u64((u64
)NSEC_PER_SEC
* atmel_tc_divisors
[i
], rate
);
297 max
= min
<< tc
->tcb_config
->counter_width
;
298 if (max
>= period_ns
)
303 * If none of the divisor are small enough to represent period_ns
304 * take slow clock (32KHz).
308 rate
= clk_get_rate(tc
->slow_clk
);
309 min
= div_u64(NSEC_PER_SEC
, rate
);
310 max
= min
<< tc
->tcb_config
->counter_width
;
312 /* If period is too big return ERANGE error */
317 duty
= div_u64(duty_ns
, min
);
318 period
= div_u64(period_ns
, min
);
321 atcbpwm
= tcbpwmc
->pwms
[pwm
->hwpwm
+ 1];
323 atcbpwm
= tcbpwmc
->pwms
[pwm
->hwpwm
- 1];
326 * PWM devices provided by TCB driver are grouped by 2:
327 * - group 0: PWM 0 & 1
328 * - group 1: PWM 2 & 3
329 * - group 2: PWM 4 & 5
331 * PWM devices in a given group must be configured with the
334 * We're checking the period value of the second PWM device
335 * in this group before applying the new config.
337 if ((atcbpwm
&& atcbpwm
->duty
> 0 &&
338 atcbpwm
->duty
!= atcbpwm
->period
) &&
339 (atcbpwm
->div
!= i
|| atcbpwm
->period
!= period
)) {
341 "failed to configure period_ns: PWM group already configured with a different value\n");
345 tcbpwm
->period
= period
;
349 /* If the PWM is enabled, call enable to apply the new conf */
350 if (pwm_is_enabled(pwm
))
351 atmel_tcb_pwm_enable(chip
, pwm
);
356 static const struct pwm_ops atmel_tcb_pwm_ops
= {
357 .request
= atmel_tcb_pwm_request
,
358 .free
= atmel_tcb_pwm_free
,
359 .config
= atmel_tcb_pwm_config
,
360 .set_polarity
= atmel_tcb_pwm_set_polarity
,
361 .enable
= atmel_tcb_pwm_enable
,
362 .disable
= atmel_tcb_pwm_disable
,
363 .owner
= THIS_MODULE
,
366 static int atmel_tcb_pwm_probe(struct platform_device
*pdev
)
368 struct atmel_tcb_pwm_chip
*tcbpwm
;
369 struct device_node
*np
= pdev
->dev
.of_node
;
374 err
= of_property_read_u32(np
, "tc-block", &tcblock
);
377 "failed to get Timer Counter Block number from device tree (error: %d)\n",
382 tc
= atmel_tc_alloc(tcblock
);
384 dev_err(&pdev
->dev
, "failed to allocate Timer Counter Block\n");
388 tcbpwm
= devm_kzalloc(&pdev
->dev
, sizeof(*tcbpwm
), GFP_KERNEL
);
389 if (tcbpwm
== NULL
) {
391 dev_err(&pdev
->dev
, "failed to allocate memory\n");
395 tcbpwm
->chip
.dev
= &pdev
->dev
;
396 tcbpwm
->chip
.ops
= &atmel_tcb_pwm_ops
;
397 tcbpwm
->chip
.of_xlate
= of_pwm_xlate_with_flags
;
398 tcbpwm
->chip
.of_pwm_n_cells
= 3;
399 tcbpwm
->chip
.base
= -1;
400 tcbpwm
->chip
.npwm
= NPWM
;
403 err
= clk_prepare_enable(tc
->slow_clk
);
407 spin_lock_init(&tcbpwm
->lock
);
409 err
= pwmchip_add(&tcbpwm
->chip
);
411 goto err_disable_clk
;
413 platform_set_drvdata(pdev
, tcbpwm
);
418 clk_disable_unprepare(tcbpwm
->tc
->slow_clk
);
426 static int atmel_tcb_pwm_remove(struct platform_device
*pdev
)
428 struct atmel_tcb_pwm_chip
*tcbpwm
= platform_get_drvdata(pdev
);
431 clk_disable_unprepare(tcbpwm
->tc
->slow_clk
);
433 err
= pwmchip_remove(&tcbpwm
->chip
);
437 atmel_tc_free(tcbpwm
->tc
);
442 static const struct of_device_id atmel_tcb_pwm_dt_ids
[] = {
443 { .compatible
= "atmel,tcb-pwm", },
446 MODULE_DEVICE_TABLE(of
, atmel_tcb_pwm_dt_ids
);
448 static struct platform_driver atmel_tcb_pwm_driver
= {
450 .name
= "atmel-tcb-pwm",
451 .of_match_table
= atmel_tcb_pwm_dt_ids
,
453 .probe
= atmel_tcb_pwm_probe
,
454 .remove
= atmel_tcb_pwm_remove
,
456 module_platform_driver(atmel_tcb_pwm_driver
);
458 MODULE_AUTHOR("Boris BREZILLON <b.brezillon@overkiz.com>");
459 MODULE_DESCRIPTION("Atmel Timer Counter Pulse Width Modulation Driver");
460 MODULE_LICENSE("GPL v2");