2 * TI OMAP2 general purpose timers emulation.
4 * Copyright (C) 2007-2008 Nokia Corporation
5 * Written by Andrzej Zaborowski <andrew@openedhand.com>
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License as
9 * published by the Free Software Foundation; either version 2 or
10 * (at your option) any later version of the License.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License along
18 * with this program; if not, see <http://www.gnu.org/licenses/>.
20 #include "qemu/osdep.h"
22 #include "qemu/timer.h"
23 #include "hw/arm/omap.h"
26 struct omap_gp_timer_s
{
35 struct omap_target_agent_s
*ta
;
41 int64_t ticks_per_sec
;
52 gpt_trigger_none
, gpt_trigger_overflow
, gpt_trigger_both
55 gpt_capture_none
, gpt_capture_rising
,
56 gpt_capture_falling
, gpt_capture_both
67 uint32_t capture_val
[2];
71 uint16_t writeh
; /* LSB */
72 uint16_t readh
; /* MSB */
75 #define GPT_TCAR_IT (1 << 2)
76 #define GPT_OVF_IT (1 << 1)
77 #define GPT_MAT_IT (1 << 0)
79 static inline void omap_gp_timer_intr(struct omap_gp_timer_s
*timer
, int it
)
81 if (timer
->it_ena
& it
) {
83 qemu_irq_raise(timer
->irq
);
86 /* Or are the status bits set even when masked?
87 * i.e. is masking applied before or after the status register? */
90 if (timer
->wu_ena
& it
)
91 qemu_irq_pulse(timer
->wkup
);
94 static inline void omap_gp_timer_out(struct omap_gp_timer_s
*timer
, int level
)
96 if (!timer
->inout
&& timer
->out_val
!= level
) {
97 timer
->out_val
= level
;
98 qemu_set_irq(timer
->out
, level
);
102 static inline uint32_t omap_gp_timer_read(struct omap_gp_timer_s
*timer
)
106 if (timer
->st
&& timer
->rate
) {
107 distance
= qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL
) - timer
->time
;
108 distance
= muldiv64(distance
, timer
->rate
, timer
->ticks_per_sec
);
110 if (distance
>= 0xffffffff - timer
->val
)
113 return timer
->val
+ distance
;
118 static inline void omap_gp_timer_sync(struct omap_gp_timer_s
*timer
)
121 timer
->val
= omap_gp_timer_read(timer
);
122 timer
->time
= qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL
);
126 static inline void omap_gp_timer_update(struct omap_gp_timer_s
*timer
)
128 int64_t expires
, matches
;
130 if (timer
->st
&& timer
->rate
) {
131 expires
= muldiv64(0x100000000ll
- timer
->val
,
132 timer
->ticks_per_sec
, timer
->rate
);
133 timer_mod(timer
->timer
, timer
->time
+ expires
);
135 if (timer
->ce
&& timer
->match_val
>= timer
->val
) {
136 matches
= muldiv64(timer
->ticks_per_sec
,
137 timer
->match_val
- timer
->val
, timer
->rate
);
138 timer_mod(timer
->match
, timer
->time
+ matches
);
140 timer_del(timer
->match
);
142 timer_del(timer
->timer
);
143 timer_del(timer
->match
);
144 omap_gp_timer_out(timer
, timer
->scpwm
);
148 static inline void omap_gp_timer_trigger(struct omap_gp_timer_s
*timer
)
151 /* TODO in overflow-and-match mode if the first event to
152 * occur is the match, don't toggle. */
153 omap_gp_timer_out(timer
, !timer
->out_val
);
155 /* TODO inverted pulse on timer->out_val == 1? */
156 qemu_irq_pulse(timer
->out
);
159 static void omap_gp_timer_tick(void *opaque
)
161 struct omap_gp_timer_s
*timer
= (struct omap_gp_timer_s
*) opaque
;
167 timer
->val
= timer
->load_val
;
168 timer
->time
= qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL
);
171 if (timer
->trigger
== gpt_trigger_overflow
||
172 timer
->trigger
== gpt_trigger_both
)
173 omap_gp_timer_trigger(timer
);
175 omap_gp_timer_intr(timer
, GPT_OVF_IT
);
176 omap_gp_timer_update(timer
);
179 static void omap_gp_timer_match(void *opaque
)
181 struct omap_gp_timer_s
*timer
= (struct omap_gp_timer_s
*) opaque
;
183 if (timer
->trigger
== gpt_trigger_both
)
184 omap_gp_timer_trigger(timer
);
186 omap_gp_timer_intr(timer
, GPT_MAT_IT
);
189 static void omap_gp_timer_input(void *opaque
, int line
, int on
)
191 struct omap_gp_timer_s
*s
= (struct omap_gp_timer_s
*) opaque
;
194 switch (s
->capture
) {
196 case gpt_capture_none
:
199 case gpt_capture_rising
:
200 trigger
= !s
->in_val
&& on
;
202 case gpt_capture_falling
:
203 trigger
= s
->in_val
&& !on
;
205 case gpt_capture_both
:
206 trigger
= (s
->in_val
== !on
);
211 if (s
->inout
&& trigger
&& s
->capt_num
< 2) {
212 s
->capture_val
[s
->capt_num
] = omap_gp_timer_read(s
);
214 if (s
->capt2
== s
->capt_num
++)
215 omap_gp_timer_intr(s
, GPT_TCAR_IT
);
219 static void omap_gp_timer_clk_update(void *opaque
, int line
, int on
)
221 struct omap_gp_timer_s
*timer
= (struct omap_gp_timer_s
*) opaque
;
223 omap_gp_timer_sync(timer
);
224 timer
->rate
= on
? omap_clk_getrate(timer
->clk
) : 0;
225 omap_gp_timer_update(timer
);
228 static void omap_gp_timer_clk_setup(struct omap_gp_timer_s
*timer
)
230 omap_clk_adduser(timer
->clk
,
231 qemu_allocate_irq(omap_gp_timer_clk_update
, timer
, 0));
232 timer
->rate
= omap_clk_getrate(timer
->clk
);
235 void omap_gp_timer_reset(struct omap_gp_timer_s
*s
)
245 s
->trigger
= gpt_trigger_none
;
246 s
->capture
= gpt_capture_none
;
255 s
->load_val
= 0x00000000;
256 s
->capture_val
[0] = 0x00000000;
257 s
->capture_val
[1] = 0x00000000;
258 s
->match_val
= 0x00000000;
259 omap_gp_timer_update(s
);
262 static uint32_t omap_gp_timer_readw(void *opaque
, hwaddr addr
)
264 struct omap_gp_timer_s
*s
= (struct omap_gp_timer_s
*) opaque
;
267 case 0x00: /* TIDR */
270 case 0x10: /* TIOCP_CFG */
273 case 0x14: /* TISTAT */
274 /* ??? When's this bit reset? */
275 return 1; /* RESETDONE */
277 case 0x18: /* TISR */
280 case 0x1c: /* TIER */
283 case 0x20: /* TWER */
286 case 0x24: /* TCLR */
287 return (s
->inout
<< 14) |
299 case 0x28: /* TCRR */
300 return omap_gp_timer_read(s
);
302 case 0x2c: /* TLDR */
305 case 0x30: /* TTGR */
308 case 0x34: /* TWPS */
309 return 0x00000000; /* No posted writes pending. */
311 case 0x38: /* TMAR */
314 case 0x3c: /* TCAR1 */
315 return s
->capture_val
[0];
317 case 0x40: /* TSICR */
318 return s
->posted
<< 2;
320 case 0x44: /* TCAR2 */
321 return s
->capture_val
[1];
328 static uint32_t omap_gp_timer_readh(void *opaque
, hwaddr addr
)
330 struct omap_gp_timer_s
*s
= (struct omap_gp_timer_s
*) opaque
;
336 ret
= omap_gp_timer_readw(opaque
, addr
);
337 s
->readh
= ret
>> 16;
342 static void omap_gp_timer_write(void *opaque
, hwaddr addr
,
345 struct omap_gp_timer_s
*s
= (struct omap_gp_timer_s
*) opaque
;
348 case 0x00: /* TIDR */
349 case 0x14: /* TISTAT */
350 case 0x34: /* TWPS */
351 case 0x3c: /* TCAR1 */
352 case 0x44: /* TCAR2 */
356 case 0x10: /* TIOCP_CFG */
357 s
->config
= value
& 0x33d;
358 if (((value
>> 3) & 3) == 3) /* IDLEMODE */
359 fprintf(stderr
, "%s: illegal IDLEMODE value in TIOCP_CFG\n",
361 if (value
& 2) /* SOFTRESET */
362 omap_gp_timer_reset(s
);
365 case 0x18: /* TISR */
366 if (value
& GPT_TCAR_IT
)
368 if (s
->status
&& !(s
->status
&= ~value
))
369 qemu_irq_lower(s
->irq
);
372 case 0x1c: /* TIER */
373 s
->it_ena
= value
& 7;
376 case 0x20: /* TWER */
377 s
->wu_ena
= value
& 7;
380 case 0x24: /* TCLR */
381 omap_gp_timer_sync(s
);
382 s
->inout
= (value
>> 14) & 1;
383 s
->capt2
= (value
>> 13) & 1;
384 s
->pt
= (value
>> 12) & 1;
385 s
->trigger
= (value
>> 10) & 3;
386 if (s
->capture
== gpt_capture_none
&&
387 ((value
>> 8) & 3) != gpt_capture_none
)
389 s
->capture
= (value
>> 8) & 3;
390 s
->scpwm
= (value
>> 7) & 1;
391 s
->ce
= (value
>> 6) & 1;
392 s
->pre
= (value
>> 5) & 1;
393 s
->ptv
= (value
>> 2) & 7;
394 s
->ar
= (value
>> 1) & 1;
395 s
->st
= (value
>> 0) & 1;
396 if (s
->inout
&& s
->trigger
!= gpt_trigger_none
)
397 fprintf(stderr
, "%s: GP timer pin must be an output "
398 "for this trigger mode\n", __FUNCTION__
);
399 if (!s
->inout
&& s
->capture
!= gpt_capture_none
)
400 fprintf(stderr
, "%s: GP timer pin must be an input "
401 "for this capture mode\n", __FUNCTION__
);
402 if (s
->trigger
== gpt_trigger_none
)
403 omap_gp_timer_out(s
, s
->scpwm
);
404 /* TODO: make sure this doesn't overflow 32-bits */
405 s
->ticks_per_sec
= NANOSECONDS_PER_SECOND
<< (s
->pre
? s
->ptv
+ 1 : 0);
406 omap_gp_timer_update(s
);
409 case 0x28: /* TCRR */
410 s
->time
= qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL
);
412 omap_gp_timer_update(s
);
415 case 0x2c: /* TLDR */
419 case 0x30: /* TTGR */
420 s
->time
= qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL
);
421 s
->val
= s
->load_val
;
422 omap_gp_timer_update(s
);
425 case 0x38: /* TMAR */
426 omap_gp_timer_sync(s
);
427 s
->match_val
= value
;
428 omap_gp_timer_update(s
);
431 case 0x40: /* TSICR */
432 s
->posted
= (value
>> 2) & 1;
433 if (value
& 2) /* How much exactly are we supposed to reset? */
434 omap_gp_timer_reset(s
);
442 static void omap_gp_timer_writeh(void *opaque
, hwaddr addr
,
445 struct omap_gp_timer_s
*s
= (struct omap_gp_timer_s
*) opaque
;
448 omap_gp_timer_write(opaque
, addr
, (value
<< 16) | s
->writeh
);
450 s
->writeh
= (uint16_t) value
;
453 static const MemoryRegionOps omap_gp_timer_ops
= {
456 omap_badwidth_read32
,
461 omap_badwidth_write32
,
462 omap_gp_timer_writeh
,
466 .endianness
= DEVICE_NATIVE_ENDIAN
,
469 struct omap_gp_timer_s
*omap_gp_timer_init(struct omap_target_agent_s
*ta
,
470 qemu_irq irq
, omap_clk fclk
, omap_clk iclk
)
472 struct omap_gp_timer_s
*s
= g_new0(struct omap_gp_timer_s
, 1);
477 s
->timer
= timer_new_ns(QEMU_CLOCK_VIRTUAL
, omap_gp_timer_tick
, s
);
478 s
->match
= timer_new_ns(QEMU_CLOCK_VIRTUAL
, omap_gp_timer_match
, s
);
479 s
->in
= qemu_allocate_irq(omap_gp_timer_input
, s
, 0);
480 omap_gp_timer_reset(s
);
481 omap_gp_timer_clk_setup(s
);
483 memory_region_init_io(&s
->iomem
, NULL
, &omap_gp_timer_ops
, s
, "omap.gptimer",
484 omap_l4_region_size(ta
, 0));
485 omap_l4_attach(ta
, 0, &s
->iomem
);