[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [PATCH 08/20] hw/timer: Renesas TMU/CMT module.
From: |
Philippe Mathieu-Daudé |
Subject: |
Re: [PATCH 08/20] hw/timer: Renesas TMU/CMT module. |
Date: |
Sun, 25 Oct 2020 00:47:47 +0200 |
User-agent: |
Mozilla/5.0 (X11; Linux x86_64; rv:78.0) Gecko/20100101 Thunderbird/78.3.1 |
On 8/27/20 2:38 PM, Yoshinori Sato wrote:
TMU - SH4 Timer module.
CMT - Compare and match timer used by some Renesas MCUs.
The two modules have similar interfaces and have been merged.
Signed-off-by: Yoshinori Sato <ysato@users.sourceforge.jp>
---
include/hw/timer/renesas_timer.h | 103 +++++
hw/timer/renesas_timer.c | 639 +++++++++++++++++++++++++++++++
hw/timer/Kconfig | 4 +-
hw/timer/meson.build | 2 +-
4 files changed, 745 insertions(+), 3 deletions(-)
create mode 100644 include/hw/timer/renesas_timer.h
create mode 100644 hw/timer/renesas_timer.c
...
+static void update_clk(RenesasTimerBaseState *tmr, int ch)
+{
+ RenesasTimerBaseClass *tc = RenesasTimer_GET_CLASS(tmr);
+ int t;
+ t = tc->divrate(tmr, ch);
+ if (t > 0) {
+ t = tmr->input_freq / t;
If the clock is connected between INIT and REALIZE,
then t=0 and ...
+ tmr->ch[ch].clk = NANOSECONDS_PER_SECOND / t;
... you get a DIV#0 here.
You can avoid it using clock_get_hz(tmr->pck) instead of
tmr->input_freq, which can be removed IMO.
+ } else {
+ tmr->ch[ch].clk = 0;
+ }
+}
...
+static void tmr_pck_update(void *opaque)
+{
+ RenesasTimerBaseState *tmr = RenesasTimerBase(opaque);
+ int64_t now;
+ int i;
+ struct rtimer_ch *ch;
+ for (i = 0; i < TIMER_CH_CMT; i++) {
+ if (tmr->ch[i].start) {
+ tmr->ch[i].cnt = read_tcnt(tmr, i);
+ }
+ }
+ if (clock_is_enabled(tmr->pck)) {
+ tmr->input_freq = clock_get_hz(tmr->pck);
+ now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
+ for (i = 0; i < TIMER_CH_CMT; i++) {
+ update_clk(tmr, i);
+ ch = &tmr->ch[i];
+ if (ch->start) {
+ ch->next = ch->base = now;
+ if (tmr->direction == countup) {
+ ch->next += (ch->cor - ch->cnt) * ch->clk;
+ } else {
+ ch->next += ch->cnt * ch->clk;
+ }
+ timer_mod(ch->timer, ch->next);
+ }
+ }
+ } else {
+ for (i = 0; i < TIMER_CH_CMT; i++) {
+ if (tmr->ch[i].timer) {
+ timer_del(tmr->ch[i].timer);
+ }
+ }
+ }
+}
...
+static void cmt_init(Object *obj)
+{
+ SysBusDevice *d = SYS_BUS_DEVICE(obj);
+ RenesasCMTState *cmt = RenesasCMT(obj);
+ RenesasTimerBaseState *tmr = RenesasTimerBase(cmt);
+ int i;
+
+ tmr->direction = countup;
+ memory_region_init_io(&tmr->memory, obj, &cmt_ops,
+ tmr, "renesas-cmt", 0x10);
+ sysbus_init_mmio(d, &tmr->memory);
+
+ for (i = 0; i < TIMER_CH_CMT; i++) {
+ sysbus_init_irq(d, &tmr->ch[i].irq);
+ }
+ tmr->pck = qdev_init_clock_in(DEVICE(obj), "pck",
+ tmr_pck_update, tmr);
+}
...
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- Re: [PATCH 08/20] hw/timer: Renesas TMU/CMT module.,
Philippe Mathieu-Daudé <=