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"
22 #include "hw/arm/omap.h"
25 struct omap_gp_timer_s
{
34 struct omap_target_agent_s
*ta
;
40 int64_t ticks_per_sec
;
51 gpt_trigger_none
, gpt_trigger_overflow
, gpt_trigger_both
54 gpt_capture_none
, gpt_capture_rising
,
55 gpt_capture_falling
, gpt_capture_both
66 uint32_t capture_val
[2];
70 uint16_t writeh
; /* LSB */
71 uint16_t readh
; /* MSB */
74 #define GPT_TCAR_IT (1 << 2)
75 #define GPT_OVF_IT (1 << 1)
76 #define GPT_MAT_IT (1 << 0)
78 static inline void omap_gp_timer_intr(struct omap_gp_timer_s
*timer
, int it
)
80 if (timer
->it_ena
& it
) {
82 qemu_irq_raise(timer
->irq
);
85 /* Or are the status bits set even when masked?
86 * i.e. is masking applied before or after the status register? */
89 if (timer
->wu_ena
& it
)
90 qemu_irq_pulse(timer
->wkup
);
93 static inline void omap_gp_timer_out(struct omap_gp_timer_s
*timer
, int level
)
95 if (!timer
->inout
&& timer
->out_val
!= level
) {
96 timer
->out_val
= level
;
97 qemu_set_irq(timer
->out
, level
);
101 static inline uint32_t omap_gp_timer_read(struct omap_gp_timer_s
*timer
)
105 if (timer
->st
&& timer
->rate
) {
106 distance
= qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL
) - timer
->time
;
107 distance
= muldiv64(distance
, timer
->rate
, timer
->ticks_per_sec
);
109 if (distance
>= 0xffffffff - timer
->val
)
112 return timer
->val
+ distance
;
117 static inline void omap_gp_timer_sync(struct omap_gp_timer_s
*timer
)
120 timer
->val
= omap_gp_timer_read(timer
);
121 timer
->time
= qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL
);
125 static inline void omap_gp_timer_update(struct omap_gp_timer_s
*timer
)
127 int64_t expires
, matches
;
129 if (timer
->st
&& timer
->rate
) {
130 expires
= muldiv64(0x100000000ll
- timer
->val
,
131 timer
->ticks_per_sec
, timer
->rate
);
132 timer_mod(timer
->timer
, timer
->time
+ expires
);
134 if (timer
->ce
&& timer
->match_val
>= timer
->val
) {
135 matches
= muldiv64(timer
->match_val
- timer
->val
,
136 timer
->ticks_per_sec
, timer
->rate
);
137 timer_mod(timer
->match
, timer
->time
+ matches
);
139 timer_del(timer
->match
);
141 timer_del(timer
->timer
);
142 timer_del(timer
->match
);
143 omap_gp_timer_out(timer
, timer
->scpwm
);
147 static inline void omap_gp_timer_trigger(struct omap_gp_timer_s
*timer
)
150 /* TODO in overflow-and-match mode if the first event to
151 * occur is the match, don't toggle. */
152 omap_gp_timer_out(timer
, !timer
->out_val
);
154 /* TODO inverted pulse on timer->out_val == 1? */
155 qemu_irq_pulse(timer
->out
);
158 static void omap_gp_timer_tick(void *opaque
)
160 struct omap_gp_timer_s
*timer
= (struct omap_gp_timer_s
*) opaque
;
166 timer
->val
= timer
->load_val
;
167 timer
->time
= qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL
);
170 if (timer
->trigger
== gpt_trigger_overflow
||
171 timer
->trigger
== gpt_trigger_both
)
172 omap_gp_timer_trigger(timer
);
174 omap_gp_timer_intr(timer
, GPT_OVF_IT
);
175 omap_gp_timer_update(timer
);
178 static void omap_gp_timer_match(void *opaque
)
180 struct omap_gp_timer_s
*timer
= (struct omap_gp_timer_s
*) opaque
;
182 if (timer
->trigger
== gpt_trigger_both
)
183 omap_gp_timer_trigger(timer
);
185 omap_gp_timer_intr(timer
, GPT_MAT_IT
);
188 static void omap_gp_timer_input(void *opaque
, int line
, int on
)
190 struct omap_gp_timer_s
*s
= (struct omap_gp_timer_s
*) opaque
;
193 switch (s
->capture
) {
195 case gpt_capture_none
:
198 case gpt_capture_rising
:
199 trigger
= !s
->in_val
&& on
;
201 case gpt_capture_falling
:
202 trigger
= s
->in_val
&& !on
;
204 case gpt_capture_both
:
205 trigger
= (s
->in_val
== !on
);
210 if (s
->inout
&& trigger
&& s
->capt_num
< 2) {
211 s
->capture_val
[s
->capt_num
] = omap_gp_timer_read(s
);
213 if (s
->capt2
== s
->capt_num
++)
214 omap_gp_timer_intr(s
, GPT_TCAR_IT
);
218 static void omap_gp_timer_clk_update(void *opaque
, int line
, int on
)
220 struct omap_gp_timer_s
*timer
= (struct omap_gp_timer_s
*) opaque
;
222 omap_gp_timer_sync(timer
);
223 timer
->rate
= on
? omap_clk_getrate(timer
->clk
) : 0;
224 omap_gp_timer_update(timer
);
227 static void omap_gp_timer_clk_setup(struct omap_gp_timer_s
*timer
)
229 omap_clk_adduser(timer
->clk
,
230 qemu_allocate_irqs(omap_gp_timer_clk_update
, timer
, 1)[0]);
231 timer
->rate
= omap_clk_getrate(timer
->clk
);
234 void omap_gp_timer_reset(struct omap_gp_timer_s
*s
)
244 s
->trigger
= gpt_trigger_none
;
245 s
->capture
= gpt_capture_none
;
254 s
->load_val
= 0x00000000;
255 s
->capture_val
[0] = 0x00000000;
256 s
->capture_val
[1] = 0x00000000;
257 s
->match_val
= 0x00000000;
258 omap_gp_timer_update(s
);
261 static uint32_t omap_gp_timer_readw(void *opaque
, hwaddr addr
)
263 struct omap_gp_timer_s
*s
= (struct omap_gp_timer_s
*) opaque
;
266 case 0x00: /* TIDR */
269 case 0x10: /* TIOCP_CFG */
272 case 0x14: /* TISTAT */
273 /* ??? When's this bit reset? */
274 return 1; /* RESETDONE */
276 case 0x18: /* TISR */
279 case 0x1c: /* TIER */
282 case 0x20: /* TWER */
285 case 0x24: /* TCLR */
286 return (s
->inout
<< 14) |
298 case 0x28: /* TCRR */
299 return omap_gp_timer_read(s
);
301 case 0x2c: /* TLDR */
304 case 0x30: /* TTGR */
307 case 0x34: /* TWPS */
308 return 0x00000000; /* No posted writes pending. */
310 case 0x38: /* TMAR */
313 case 0x3c: /* TCAR1 */
314 return s
->capture_val
[0];
316 case 0x40: /* TSICR */
317 return s
->posted
<< 2;
319 case 0x44: /* TCAR2 */
320 return s
->capture_val
[1];
327 static uint32_t omap_gp_timer_readh(void *opaque
, hwaddr addr
)
329 struct omap_gp_timer_s
*s
= (struct omap_gp_timer_s
*) opaque
;
335 ret
= omap_gp_timer_readw(opaque
, addr
);
336 s
->readh
= ret
>> 16;
341 static void omap_gp_timer_write(void *opaque
, hwaddr addr
,
344 struct omap_gp_timer_s
*s
= (struct omap_gp_timer_s
*) opaque
;
347 case 0x00: /* TIDR */
348 case 0x14: /* TISTAT */
349 case 0x34: /* TWPS */
350 case 0x3c: /* TCAR1 */
351 case 0x44: /* TCAR2 */
355 case 0x10: /* TIOCP_CFG */
356 s
->config
= value
& 0x33d;
357 if (((value
>> 3) & 3) == 3) /* IDLEMODE */
358 fprintf(stderr
, "%s: illegal IDLEMODE value in TIOCP_CFG\n",
360 if (value
& 2) /* SOFTRESET */
361 omap_gp_timer_reset(s
);
364 case 0x18: /* TISR */
365 if (value
& GPT_TCAR_IT
)
367 if (s
->status
&& !(s
->status
&= ~value
))
368 qemu_irq_lower(s
->irq
);
371 case 0x1c: /* TIER */
372 s
->it_ena
= value
& 7;
375 case 0x20: /* TWER */
376 s
->wu_ena
= value
& 7;
379 case 0x24: /* TCLR */
380 omap_gp_timer_sync(s
);
381 s
->inout
= (value
>> 14) & 1;
382 s
->capt2
= (value
>> 13) & 1;
383 s
->pt
= (value
>> 12) & 1;
384 s
->trigger
= (value
>> 10) & 3;
385 if (s
->capture
== gpt_capture_none
&&
386 ((value
>> 8) & 3) != gpt_capture_none
)
388 s
->capture
= (value
>> 8) & 3;
389 s
->scpwm
= (value
>> 7) & 1;
390 s
->ce
= (value
>> 6) & 1;
391 s
->pre
= (value
>> 5) & 1;
392 s
->ptv
= (value
>> 2) & 7;
393 s
->ar
= (value
>> 1) & 1;
394 s
->st
= (value
>> 0) & 1;
395 if (s
->inout
&& s
->trigger
!= gpt_trigger_none
)
396 fprintf(stderr
, "%s: GP timer pin must be an output "
397 "for this trigger mode\n", __FUNCTION__
);
398 if (!s
->inout
&& s
->capture
!= gpt_capture_none
)
399 fprintf(stderr
, "%s: GP timer pin must be an input "
400 "for this capture mode\n", __FUNCTION__
);
401 if (s
->trigger
== gpt_trigger_none
)
402 omap_gp_timer_out(s
, s
->scpwm
);
403 /* TODO: make sure this doesn't overflow 32-bits */
404 s
->ticks_per_sec
= get_ticks_per_sec() << (s
->pre
? s
->ptv
+ 1 : 0);
405 omap_gp_timer_update(s
);
408 case 0x28: /* TCRR */
409 s
->time
= qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL
);
411 omap_gp_timer_update(s
);
414 case 0x2c: /* TLDR */
418 case 0x30: /* TTGR */
419 s
->time
= qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL
);
420 s
->val
= s
->load_val
;
421 omap_gp_timer_update(s
);
424 case 0x38: /* TMAR */
425 omap_gp_timer_sync(s
);
426 s
->match_val
= value
;
427 omap_gp_timer_update(s
);
430 case 0x40: /* TSICR */
431 s
->posted
= (value
>> 2) & 1;
432 if (value
& 2) /* How much exactly are we supposed to reset? */
433 omap_gp_timer_reset(s
);
441 static void omap_gp_timer_writeh(void *opaque
, hwaddr addr
,
444 struct omap_gp_timer_s
*s
= (struct omap_gp_timer_s
*) opaque
;
447 return omap_gp_timer_write(opaque
, addr
, (value
<< 16) | s
->writeh
);
449 s
->writeh
= (uint16_t) value
;
452 static const MemoryRegionOps omap_gp_timer_ops
= {
455 omap_badwidth_read32
,
460 omap_badwidth_write32
,
461 omap_gp_timer_writeh
,
465 .endianness
= DEVICE_NATIVE_ENDIAN
,
468 struct omap_gp_timer_s
*omap_gp_timer_init(struct omap_target_agent_s
*ta
,
469 qemu_irq irq
, omap_clk fclk
, omap_clk iclk
)
471 struct omap_gp_timer_s
*s
= (struct omap_gp_timer_s
*)
472 g_malloc0(sizeof(struct omap_gp_timer_s
));
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_irqs(omap_gp_timer_input
, s
, 1)[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
);