blob: 1904d8b53328fad9440b33a4cfdb391e7d2f0473 [file] [log] [blame]
Mike Frysinger780431e2007-10-21 23:37:54 +08001/*
Mike Frysingerfee40112008-02-25 15:06:07 +08002 * gptimers.c - Blackfin General Purpose Timer core API
Mike Frysinger780431e2007-10-21 23:37:54 +08003 *
Mike Frysingerfee40112008-02-25 15:06:07 +08004 * Copyright (c) 2005-2008 Analog Devices Inc.
5 * Copyright (C) 2005 John DeHority
6 * Copyright (C) 2006 Hella Aglaia GmbH (awe@aglaia-gmbh.de)
Mike Frysinger780431e2007-10-21 23:37:54 +08007 *
8 * Licensed under the GPLv2.
9 */
10
11#include <linux/kernel.h>
12#include <linux/module.h>
13
14#include <asm/io.h>
15#include <asm/blackfin.h>
16#include <asm/gptimers.h>
17
18#ifdef DEBUG
19# define tassert(expr)
20#else
21# define tassert(expr) \
22 if (!(expr)) \
Mike Frysinger4ad1ec72007-10-29 18:02:09 +080023 printk(KERN_DEBUG "%s:%s:%i: Assertion failed: " #expr "\n", __FILE__, __func__, __LINE__);
Mike Frysinger780431e2007-10-21 23:37:54 +080024#endif
25
26#define BFIN_TIMER_NUM_GROUP (BFIN_TIMER_OCTET(MAX_BLACKFIN_GPTIMERS - 1) + 1)
27
28typedef struct {
29 uint16_t config;
30 uint16_t __pad;
31 uint32_t counter;
32 uint32_t period;
33 uint32_t width;
34} GPTIMER_timer_regs;
35
36typedef struct {
37 uint16_t enable;
38 uint16_t __pad0;
39 uint16_t disable;
40 uint16_t __pad1;
41 uint32_t status;
42} GPTIMER_group_regs;
43
44static volatile GPTIMER_timer_regs *const timer_regs[MAX_BLACKFIN_GPTIMERS] =
45{
46 (GPTIMER_timer_regs *)TIMER0_CONFIG,
47 (GPTIMER_timer_regs *)TIMER1_CONFIG,
48 (GPTIMER_timer_regs *)TIMER2_CONFIG,
49#if (MAX_BLACKFIN_GPTIMERS > 3)
50 (GPTIMER_timer_regs *)TIMER3_CONFIG,
51 (GPTIMER_timer_regs *)TIMER4_CONFIG,
52 (GPTIMER_timer_regs *)TIMER5_CONFIG,
53 (GPTIMER_timer_regs *)TIMER6_CONFIG,
54 (GPTIMER_timer_regs *)TIMER7_CONFIG,
55#endif
56#if (MAX_BLACKFIN_GPTIMERS > 8)
57 (GPTIMER_timer_regs *)TIMER8_CONFIG,
58 (GPTIMER_timer_regs *)TIMER9_CONFIG,
59 (GPTIMER_timer_regs *)TIMER10_CONFIG,
60 (GPTIMER_timer_regs *)TIMER11_CONFIG,
61#endif
62};
63
64static volatile GPTIMER_group_regs *const group_regs[BFIN_TIMER_NUM_GROUP] =
65{
66 (GPTIMER_group_regs *)TIMER0_GROUP_REG,
67#if (MAX_BLACKFIN_GPTIMERS > 8)
68 (GPTIMER_group_regs *)TIMER8_GROUP_REG,
69#endif
70};
71
Mike Frysinger4ad1ec72007-10-29 18:02:09 +080072static uint32_t const trun_mask[MAX_BLACKFIN_GPTIMERS] =
Mike Frysinger780431e2007-10-21 23:37:54 +080073{
74 TIMER_STATUS_TRUN0,
75 TIMER_STATUS_TRUN1,
76 TIMER_STATUS_TRUN2,
77#if (MAX_BLACKFIN_GPTIMERS > 3)
78 TIMER_STATUS_TRUN3,
79 TIMER_STATUS_TRUN4,
80 TIMER_STATUS_TRUN5,
81 TIMER_STATUS_TRUN6,
82 TIMER_STATUS_TRUN7,
83#endif
84#if (MAX_BLACKFIN_GPTIMERS > 8)
85 TIMER_STATUS_TRUN8,
86 TIMER_STATUS_TRUN9,
87 TIMER_STATUS_TRUN10,
88 TIMER_STATUS_TRUN11,
89#endif
90};
91
Mike Frysinger4ad1ec72007-10-29 18:02:09 +080092static uint32_t const tovf_mask[MAX_BLACKFIN_GPTIMERS] =
93{
94 TIMER_STATUS_TOVF0,
95 TIMER_STATUS_TOVF1,
96 TIMER_STATUS_TOVF2,
97#if (MAX_BLACKFIN_GPTIMERS > 3)
98 TIMER_STATUS_TOVF3,
99 TIMER_STATUS_TOVF4,
100 TIMER_STATUS_TOVF5,
101 TIMER_STATUS_TOVF6,
102 TIMER_STATUS_TOVF7,
103#endif
104#if (MAX_BLACKFIN_GPTIMERS > 8)
105 TIMER_STATUS_TOVF8,
106 TIMER_STATUS_TOVF9,
107 TIMER_STATUS_TOVF10,
108 TIMER_STATUS_TOVF11,
109#endif
110};
111
112static uint32_t const timil_mask[MAX_BLACKFIN_GPTIMERS] =
Mike Frysinger780431e2007-10-21 23:37:54 +0800113{
114 TIMER_STATUS_TIMIL0,
115 TIMER_STATUS_TIMIL1,
116 TIMER_STATUS_TIMIL2,
117#if (MAX_BLACKFIN_GPTIMERS > 3)
118 TIMER_STATUS_TIMIL3,
119 TIMER_STATUS_TIMIL4,
120 TIMER_STATUS_TIMIL5,
121 TIMER_STATUS_TIMIL6,
122 TIMER_STATUS_TIMIL7,
123#endif
124#if (MAX_BLACKFIN_GPTIMERS > 8)
125 TIMER_STATUS_TIMIL8,
126 TIMER_STATUS_TIMIL9,
127 TIMER_STATUS_TIMIL10,
128 TIMER_STATUS_TIMIL11,
129#endif
130};
131
132void set_gptimer_pwidth(int timer_id, uint32_t value)
133{
134 tassert(timer_id < MAX_BLACKFIN_GPTIMERS);
135 timer_regs[timer_id]->width = value;
136 SSYNC();
137}
138EXPORT_SYMBOL(set_gptimer_pwidth);
139
140uint32_t get_gptimer_pwidth(int timer_id)
141{
142 tassert(timer_id < MAX_BLACKFIN_GPTIMERS);
143 return timer_regs[timer_id]->width;
144}
145EXPORT_SYMBOL(get_gptimer_pwidth);
146
147void set_gptimer_period(int timer_id, uint32_t period)
148{
149 tassert(timer_id < MAX_BLACKFIN_GPTIMERS);
150 timer_regs[timer_id]->period = period;
151 SSYNC();
152}
153EXPORT_SYMBOL(set_gptimer_period);
154
155uint32_t get_gptimer_period(int timer_id)
156{
157 tassert(timer_id < MAX_BLACKFIN_GPTIMERS);
158 return timer_regs[timer_id]->period;
159}
160EXPORT_SYMBOL(get_gptimer_period);
161
162uint32_t get_gptimer_count(int timer_id)
163{
164 tassert(timer_id < MAX_BLACKFIN_GPTIMERS);
165 return timer_regs[timer_id]->counter;
166}
167EXPORT_SYMBOL(get_gptimer_count);
168
169uint32_t get_gptimer_status(int group)
170{
171 tassert(group < BFIN_TIMER_NUM_GROUP);
172 return group_regs[group]->status;
173}
174EXPORT_SYMBOL(get_gptimer_status);
175
176void set_gptimer_status(int group, uint32_t value)
177{
178 tassert(group < BFIN_TIMER_NUM_GROUP);
179 group_regs[group]->status = value;
180 SSYNC();
181}
182EXPORT_SYMBOL(set_gptimer_status);
183
184uint16_t get_gptimer_intr(int timer_id)
185{
186 tassert(timer_id < MAX_BLACKFIN_GPTIMERS);
Mike Frysinger4ad1ec72007-10-29 18:02:09 +0800187 return (group_regs[BFIN_TIMER_OCTET(timer_id)]->status & timil_mask[timer_id]) ? 1 : 0;
Mike Frysinger780431e2007-10-21 23:37:54 +0800188}
189EXPORT_SYMBOL(get_gptimer_intr);
190
191void clear_gptimer_intr(int timer_id)
192{
193 tassert(timer_id < MAX_BLACKFIN_GPTIMERS);
Mike Frysinger4ad1ec72007-10-29 18:02:09 +0800194 group_regs[BFIN_TIMER_OCTET(timer_id)]->status = timil_mask[timer_id];
Mike Frysinger780431e2007-10-21 23:37:54 +0800195}
196EXPORT_SYMBOL(clear_gptimer_intr);
197
Mike Frysinger4ad1ec72007-10-29 18:02:09 +0800198uint16_t get_gptimer_over(int timer_id)
199{
200 tassert(timer_id < MAX_BLACKFIN_GPTIMERS);
201 return (group_regs[BFIN_TIMER_OCTET(timer_id)]->status & tovf_mask[timer_id]) ? 1 : 0;
202}
203EXPORT_SYMBOL(get_gptimer_over);
204
205void clear_gptimer_over(int timer_id)
206{
207 tassert(timer_id < MAX_BLACKFIN_GPTIMERS);
208 group_regs[BFIN_TIMER_OCTET(timer_id)]->status = tovf_mask[timer_id];
209}
210EXPORT_SYMBOL(clear_gptimer_over);
211
Mike Frysinger780431e2007-10-21 23:37:54 +0800212void set_gptimer_config(int timer_id, uint16_t config)
213{
214 tassert(timer_id < MAX_BLACKFIN_GPTIMERS);
215 timer_regs[timer_id]->config = config;
216 SSYNC();
217}
218EXPORT_SYMBOL(set_gptimer_config);
219
220uint16_t get_gptimer_config(int timer_id)
221{
222 tassert(timer_id < MAX_BLACKFIN_GPTIMERS);
223 return timer_regs[timer_id]->config;
224}
225EXPORT_SYMBOL(get_gptimer_config);
226
227void enable_gptimers(uint16_t mask)
228{
229 int i;
230 tassert((mask & ~BLACKFIN_GPTIMER_IDMASK) == 0);
231 for (i = 0; i < BFIN_TIMER_NUM_GROUP; ++i) {
232 group_regs[i]->enable = mask & 0xFF;
233 mask >>= 8;
234 }
235 SSYNC();
236}
237EXPORT_SYMBOL(enable_gptimers);
238
239void disable_gptimers(uint16_t mask)
240{
241 int i;
242 uint16_t m = mask;
243 tassert((mask & ~BLACKFIN_GPTIMER_IDMASK) == 0);
244 for (i = 0; i < BFIN_TIMER_NUM_GROUP; ++i) {
245 group_regs[i]->disable = m & 0xFF;
246 m >>= 8;
247 }
248 for (i = 0; i < MAX_BLACKFIN_GPTIMERS; ++i)
249 if (mask & (1 << i))
Mike Frysinger4ad1ec72007-10-29 18:02:09 +0800250 group_regs[BFIN_TIMER_OCTET(i)]->status |= trun_mask[i];
Mike Frysinger780431e2007-10-21 23:37:54 +0800251 SSYNC();
252}
253EXPORT_SYMBOL(disable_gptimers);
254
255void set_gptimer_pulse_hi(int timer_id)
256{
257 tassert(timer_id < MAX_BLACKFIN_GPTIMERS);
258 timer_regs[timer_id]->config |= TIMER_PULSE_HI;
259 SSYNC();
260}
261EXPORT_SYMBOL(set_gptimer_pulse_hi);
262
263void clear_gptimer_pulse_hi(int timer_id)
264{
265 tassert(timer_id < MAX_BLACKFIN_GPTIMERS);
266 timer_regs[timer_id]->config &= ~TIMER_PULSE_HI;
267 SSYNC();
268}
269EXPORT_SYMBOL(clear_gptimer_pulse_hi);
270
271uint16_t get_enabled_gptimers(void)
272{
273 int i;
274 uint16_t result = 0;
275 for (i = 0; i < BFIN_TIMER_NUM_GROUP; ++i)
276 result |= (group_regs[i]->enable << (i << 3));
277 return result;
278}
279EXPORT_SYMBOL(get_enabled_gptimers);
280
281MODULE_AUTHOR("Axel Weiss (awe@aglaia-gmbh.de)");
282MODULE_DESCRIPTION("Blackfin General Purpose Timers API");
283MODULE_LICENSE("GPL");