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/>.
21 #include "qemu-timer.h"
25 struct omap_gp_timer_s
{
33 struct omap_target_agent_s
*ta
;
39 int64_t ticks_per_sec
;
50 gpt_trigger_none
, gpt_trigger_overflow
, gpt_trigger_both
53 gpt_capture_none
, gpt_capture_rising
,
54 gpt_capture_falling
, gpt_capture_both
65 uint32_t capture_val
[2];
69 uint16_t writeh
; /* LSB */
70 uint16_t readh
; /* MSB */
73 #define GPT_TCAR_IT (1 << 2)
74 #define GPT_OVF_IT (1 << 1)
75 #define GPT_MAT_IT (1 << 0)
77 static inline void omap_gp_timer_intr(struct omap_gp_timer_s
*timer
, int it
)
79 if (timer
->it_ena
& it
) {
81 qemu_irq_raise(timer
->irq
);
84 /* Or are the status bits set even when masked?
85 * i.e. is masking applied before or after the status register? */
88 if (timer
->wu_ena
& it
)
89 qemu_irq_pulse(timer
->wkup
);
92 static inline void omap_gp_timer_out(struct omap_gp_timer_s
*timer
, int level
)
94 if (!timer
->inout
&& timer
->out_val
!= level
) {
95 timer
->out_val
= level
;
96 qemu_set_irq(timer
->out
, level
);
100 static inline uint32_t omap_gp_timer_read(struct omap_gp_timer_s
*timer
)
104 if (timer
->st
&& timer
->rate
) {
105 distance
= qemu_get_clock(vm_clock
) - timer
->time
;
106 distance
= muldiv64(distance
, timer
->rate
, timer
->ticks_per_sec
);
108 if (distance
>= 0xffffffff - timer
->val
)
111 return timer
->val
+ distance
;
116 static inline void omap_gp_timer_sync(struct omap_gp_timer_s
*timer
)
119 timer
->val
= omap_gp_timer_read(timer
);
120 timer
->time
= qemu_get_clock(vm_clock
);
124 static inline void omap_gp_timer_update(struct omap_gp_timer_s
*timer
)
126 int64_t expires
, matches
;
128 if (timer
->st
&& timer
->rate
) {
129 expires
= muldiv64(0x100000000ll
- timer
->val
,
130 timer
->ticks_per_sec
, timer
->rate
);
131 qemu_mod_timer(timer
->timer
, timer
->time
+ expires
);
133 if (timer
->ce
&& timer
->match_val
>= timer
->val
) {
134 matches
= muldiv64(timer
->match_val
- timer
->val
,
135 timer
->ticks_per_sec
, timer
->rate
);
136 qemu_mod_timer(timer
->match
, timer
->time
+ matches
);
138 qemu_del_timer(timer
->match
);
140 qemu_del_timer(timer
->timer
);
141 qemu_del_timer(timer
->match
);
142 omap_gp_timer_out(timer
, timer
->scpwm
);
146 static inline void omap_gp_timer_trigger(struct omap_gp_timer_s
*timer
)
149 /* TODO in overflow-and-match mode if the first event to
150 * occur is the match, don't toggle. */
151 omap_gp_timer_out(timer
, !timer
->out_val
);
153 /* TODO inverted pulse on timer->out_val == 1? */
154 qemu_irq_pulse(timer
->out
);
157 static void omap_gp_timer_tick(void *opaque
)
159 struct omap_gp_timer_s
*timer
= (struct omap_gp_timer_s
*) opaque
;
165 timer
->val
= timer
->load_val
;
166 timer
->time
= qemu_get_clock(vm_clock
);
169 if (timer
->trigger
== gpt_trigger_overflow
||
170 timer
->trigger
== gpt_trigger_both
)
171 omap_gp_timer_trigger(timer
);
173 omap_gp_timer_intr(timer
, GPT_OVF_IT
);
174 omap_gp_timer_update(timer
);
177 static void omap_gp_timer_match(void *opaque
)
179 struct omap_gp_timer_s
*timer
= (struct omap_gp_timer_s
*) opaque
;
181 if (timer
->trigger
== gpt_trigger_both
)
182 omap_gp_timer_trigger(timer
);
184 omap_gp_timer_intr(timer
, GPT_MAT_IT
);
187 static void omap_gp_timer_input(void *opaque
, int line
, int on
)
189 struct omap_gp_timer_s
*s
= (struct omap_gp_timer_s
*) opaque
;
192 switch (s
->capture
) {
194 case gpt_capture_none
:
197 case gpt_capture_rising
:
198 trigger
= !s
->in_val
&& on
;
200 case gpt_capture_falling
:
201 trigger
= s
->in_val
&& !on
;
203 case gpt_capture_both
:
204 trigger
= (s
->in_val
== !on
);
209 if (s
->inout
&& trigger
&& s
->capt_num
< 2) {
210 s
->capture_val
[s
->capt_num
] = omap_gp_timer_read(s
);
212 if (s
->capt2
== s
->capt_num
++)
213 omap_gp_timer_intr(s
, GPT_TCAR_IT
);
217 static void omap_gp_timer_clk_update(void *opaque
, int line
, int on
)
219 struct omap_gp_timer_s
*timer
= (struct omap_gp_timer_s
*) opaque
;
221 omap_gp_timer_sync(timer
);
222 timer
->rate
= on
? omap_clk_getrate(timer
->clk
) : 0;
223 omap_gp_timer_update(timer
);
226 static void omap_gp_timer_clk_setup(struct omap_gp_timer_s
*timer
)
228 omap_clk_adduser(timer
->clk
,
229 qemu_allocate_irqs(omap_gp_timer_clk_update
, timer
, 1)[0]);
230 timer
->rate
= omap_clk_getrate(timer
->clk
);
233 void omap_gp_timer_reset(struct omap_gp_timer_s
*s
)
243 s
->trigger
= gpt_trigger_none
;
244 s
->capture
= gpt_capture_none
;
253 s
->load_val
= 0x00000000;
254 s
->capture_val
[0] = 0x00000000;
255 s
->capture_val
[1] = 0x00000000;
256 s
->match_val
= 0x00000000;
257 omap_gp_timer_update(s
);
260 static uint32_t omap_gp_timer_readw(void *opaque
, target_phys_addr_t addr
)
262 struct omap_gp_timer_s
*s
= (struct omap_gp_timer_s
*) opaque
;
265 case 0x00: /* TIDR */
268 case 0x10: /* TIOCP_CFG */
271 case 0x14: /* TISTAT */
272 /* ??? When's this bit reset? */
273 return 1; /* RESETDONE */
275 case 0x18: /* TISR */
278 case 0x1c: /* TIER */
281 case 0x20: /* TWER */
284 case 0x24: /* TCLR */
285 return (s
->inout
<< 14) |
297 case 0x28: /* TCRR */
298 return omap_gp_timer_read(s
);
300 case 0x2c: /* TLDR */
303 case 0x30: /* TTGR */
306 case 0x34: /* TWPS */
307 return 0x00000000; /* No posted writes pending. */
309 case 0x38: /* TMAR */
312 case 0x3c: /* TCAR1 */
313 return s
->capture_val
[0];
315 case 0x40: /* TSICR */
316 return s
->posted
<< 2;
318 case 0x44: /* TCAR2 */
319 return s
->capture_val
[1];
326 static uint32_t omap_gp_timer_readh(void *opaque
, target_phys_addr_t addr
)
328 struct omap_gp_timer_s
*s
= (struct omap_gp_timer_s
*) opaque
;
334 ret
= omap_gp_timer_readw(opaque
, addr
);
335 s
->readh
= ret
>> 16;
340 static CPUReadMemoryFunc
* const omap_gp_timer_readfn
[] = {
341 omap_badwidth_read32
,
346 static void omap_gp_timer_write(void *opaque
, target_phys_addr_t addr
,
349 struct omap_gp_timer_s
*s
= (struct omap_gp_timer_s
*) opaque
;
352 case 0x00: /* TIDR */
353 case 0x14: /* TISTAT */
354 case 0x34: /* TWPS */
355 case 0x3c: /* TCAR1 */
356 case 0x44: /* TCAR2 */
360 case 0x10: /* TIOCP_CFG */
361 s
->config
= value
& 0x33d;
362 if (((value
>> 3) & 3) == 3) /* IDLEMODE */
363 fprintf(stderr
, "%s: illegal IDLEMODE value in TIOCP_CFG\n",
365 if (value
& 2) /* SOFTRESET */
366 omap_gp_timer_reset(s
);
369 case 0x18: /* TISR */
370 if (value
& GPT_TCAR_IT
)
372 if (s
->status
&& !(s
->status
&= ~value
))
373 qemu_irq_lower(s
->irq
);
376 case 0x1c: /* TIER */
377 s
->it_ena
= value
& 7;
380 case 0x20: /* TWER */
381 s
->wu_ena
= value
& 7;
384 case 0x24: /* TCLR */
385 omap_gp_timer_sync(s
);
386 s
->inout
= (value
>> 14) & 1;
387 s
->capt2
= (value
>> 13) & 1;
388 s
->pt
= (value
>> 12) & 1;
389 s
->trigger
= (value
>> 10) & 3;
390 if (s
->capture
== gpt_capture_none
&&
391 ((value
>> 8) & 3) != gpt_capture_none
)
393 s
->capture
= (value
>> 8) & 3;
394 s
->scpwm
= (value
>> 7) & 1;
395 s
->ce
= (value
>> 6) & 1;
396 s
->pre
= (value
>> 5) & 1;
397 s
->ptv
= (value
>> 2) & 7;
398 s
->ar
= (value
>> 1) & 1;
399 s
->st
= (value
>> 0) & 1;
400 if (s
->inout
&& s
->trigger
!= gpt_trigger_none
)
401 fprintf(stderr
, "%s: GP timer pin must be an output "
402 "for this trigger mode\n", __FUNCTION__
);
403 if (!s
->inout
&& s
->capture
!= gpt_capture_none
)
404 fprintf(stderr
, "%s: GP timer pin must be an input "
405 "for this capture mode\n", __FUNCTION__
);
406 if (s
->trigger
== gpt_trigger_none
)
407 omap_gp_timer_out(s
, s
->scpwm
);
408 /* TODO: make sure this doesn't overflow 32-bits */
409 s
->ticks_per_sec
= get_ticks_per_sec() << (s
->pre
? s
->ptv
+ 1 : 0);
410 omap_gp_timer_update(s
);
413 case 0x28: /* TCRR */
414 s
->time
= qemu_get_clock(vm_clock
);
416 omap_gp_timer_update(s
);
419 case 0x2c: /* TLDR */
423 case 0x30: /* TTGR */
424 s
->time
= qemu_get_clock(vm_clock
);
425 s
->val
= s
->load_val
;
426 omap_gp_timer_update(s
);
429 case 0x38: /* TMAR */
430 omap_gp_timer_sync(s
);
431 s
->match_val
= value
;
432 omap_gp_timer_update(s
);
435 case 0x40: /* TSICR */
436 s
->posted
= (value
>> 2) & 1;
437 if (value
& 2) /* How much exactly are we supposed to reset? */
438 omap_gp_timer_reset(s
);
446 static void omap_gp_timer_writeh(void *opaque
, target_phys_addr_t addr
,
449 struct omap_gp_timer_s
*s
= (struct omap_gp_timer_s
*) opaque
;
452 return omap_gp_timer_write(opaque
, addr
, (value
<< 16) | s
->writeh
);
454 s
->writeh
= (uint16_t) value
;
457 static CPUWriteMemoryFunc
* const omap_gp_timer_writefn
[] = {
458 omap_badwidth_write32
,
459 omap_gp_timer_writeh
,
463 struct omap_gp_timer_s
*omap_gp_timer_init(struct omap_target_agent_s
*ta
,
464 qemu_irq irq
, omap_clk fclk
, omap_clk iclk
)
467 struct omap_gp_timer_s
*s
= (struct omap_gp_timer_s
*)
468 qemu_mallocz(sizeof(struct omap_gp_timer_s
));
473 s
->timer
= qemu_new_timer(vm_clock
, omap_gp_timer_tick
, s
);
474 s
->match
= qemu_new_timer(vm_clock
, omap_gp_timer_match
, s
);
475 s
->in
= qemu_allocate_irqs(omap_gp_timer_input
, s
, 1)[0];
476 omap_gp_timer_reset(s
);
477 omap_gp_timer_clk_setup(s
);
479 iomemtype
= l4_register_io_memory(omap_gp_timer_readfn
,
480 omap_gp_timer_writefn
, s
);
481 omap_l4_attach(ta
, 0, iomemtype
);