2 * TI OMAP2 general purpose timers emulation.
4 * Copyright (C) 2007-2008 Nokia Corporation
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_irq(omap_gp_timer_clk_update, timer, 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 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 = g_new0(struct omap_gp_timer_s, 1);
476 s->timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, omap_gp_timer_tick, s);
477 s->match = timer_new_ns(QEMU_CLOCK_VIRTUAL, omap_gp_timer_match, s);
478 s->in = qemu_allocate_irq(omap_gp_timer_input, s, 0);
479 omap_gp_timer_reset(s);
480 omap_gp_timer_clk_setup(s);
482 memory_region_init_io(&s->iomem, NULL, &omap_gp_timer_ops, s, "omap.gptimer",
483 omap_l4_region_size(ta, 0));
484 omap_l4_attach(ta, 0, &s->iomem);