Commit | Line | Data |
---|---|---|
9a1e8eb1 DB |
1 | #ifndef __LINUX_ATMEL_PWM_H |
2 | #define __LINUX_ATMEL_PWM_H | |
3 | ||
4 | /** | |
5 | * struct pwm_channel - driver handle to a PWM channel | |
6 | * @regs: base of this channel's registers | |
7 | * @index: number of this channel (0..31) | |
8 | * @mck: base clock rate, which can be prescaled and maybe subdivided | |
9 | * | |
10 | * Drivers initialize a pwm_channel structure using pwm_channel_alloc(). | |
11 | * Then they configure its clock rate (derived from MCK), alignment, | |
12 | * polarity, and duty cycle by writing directly to the channel registers, | |
13 | * before enabling the channel by calling pwm_channel_enable(). | |
14 | * | |
15 | * After emitting a PWM signal for the desired length of time, drivers | |
16 | * may then pwm_channel_disable() or pwm_channel_free(). Both of these | |
17 | * disable the channel, but when it's freed the IRQ is deconfigured and | |
18 | * the channel must later be re-allocated and reconfigured. | |
19 | * | |
20 | * Note that if the period or duty cycle need to be changed while the | |
21 | * PWM channel is operating, drivers must use the PWM_CUPD double buffer | |
22 | * mechanism, either polling until they change or getting implicitly | |
23 | * notified through a once-per-period interrupt handler. | |
24 | */ | |
25 | struct pwm_channel { | |
26 | void __iomem *regs; | |
27 | unsigned index; | |
28 | unsigned long mck; | |
29 | }; | |
30 | ||
31 | extern int pwm_channel_alloc(int index, struct pwm_channel *ch); | |
32 | extern int pwm_channel_free(struct pwm_channel *ch); | |
33 | ||
34 | extern int pwm_clk_alloc(unsigned prescale, unsigned div); | |
35 | extern void pwm_clk_free(unsigned clk); | |
36 | ||
37 | extern int __pwm_channel_onoff(struct pwm_channel *ch, int enabled); | |
38 | ||
39 | #define pwm_channel_enable(ch) __pwm_channel_onoff((ch), 1) | |
40 | #define pwm_channel_disable(ch) __pwm_channel_onoff((ch), 0) | |
41 | ||
42 | /* periodic interrupts, mostly for CUPD changes to period or cycle */ | |
43 | extern int pwm_channel_handler(struct pwm_channel *ch, | |
44 | void (*handler)(struct pwm_channel *ch)); | |
45 | ||
46 | /* per-channel registers (banked at pwm_channel->regs) */ | |
47 | #define PWM_CMR 0x00 /* mode register */ | |
48 | #define PWM_CPR_CPD (1 << 10) /* set: CUPD modifies period */ | |
49 | #define PWM_CPR_CPOL (1 << 9) /* set: idle high */ | |
50 | #define PWM_CPR_CALG (1 << 8) /* set: center align */ | |
51 | #define PWM_CPR_CPRE (0xf << 0) /* mask: rate is mck/(2^pre) */ | |
52 | #define PWM_CPR_CLKA (0xb << 0) /* rate CLKA */ | |
53 | #define PWM_CPR_CLKB (0xc << 0) /* rate CLKB */ | |
54 | #define PWM_CDTY 0x04 /* duty cycle (max of CPRD) */ | |
55 | #define PWM_CPRD 0x08 /* period (count up from zero) */ | |
56 | #define PWM_CCNT 0x0c /* counter (20 bits?) */ | |
57 | #define PWM_CUPD 0x10 /* update CPRD (or CDTY) next period */ | |
58 | ||
59 | static inline void | |
60 | pwm_channel_writel(struct pwm_channel *pwmc, unsigned offset, u32 val) | |
61 | { | |
62 | __raw_writel(val, pwmc->regs + offset); | |
63 | } | |
64 | ||
65 | static inline u32 pwm_channel_readl(struct pwm_channel *pwmc, unsigned offset) | |
66 | { | |
67 | return __raw_readl(pwmc->regs + offset); | |
68 | } | |
69 | ||
70 | #endif /* __LINUX_ATMEL_PWM_H */ |