4 * Datasheet: RX62N Group, RX621 Group User's Manual: Hardware
5 * (Rev.1.40 R01UH0033EJ0140)
7 * Copyright (c) 2019 Yoshinori Sato
9 * SPDX-License-Identifier: GPL-2.0-or-later
11 * This program is free software; you can redistribute it and/or modify it
12 * under the terms and conditions of the GNU General Public License,
13 * version 2 or later, as published by the Free Software Foundation.
15 * This program is distributed in the hope it will be useful, but WITHOUT
16 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
17 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
20 * You should have received a copy of the GNU General Public License along with
21 * this program. If not, see <http://www.gnu.org/licenses/>.
24 #include "qemu/osdep.h"
27 #include "hw/registerfields.h"
28 #include "hw/qdev-properties.h"
29 #include "hw/timer/renesas_tmr.h"
30 #include "migration/vmstate.h"
33 FIELD(TCR
, CCLR
, 3, 2)
34 FIELD(TCR
, OVIE
, 5, 1)
35 FIELD(TCR
, CMIEA
, 6, 1)
36 FIELD(TCR
, CMIEB
, 7, 1)
38 FIELD(TCSR
, OSA
, 0, 2)
39 FIELD(TCSR
, OSB
, 2, 2)
40 FIELD(TCSR
, ADTE
, 4, 2)
45 FIELD(TCCR
, CKS
, 0, 3)
46 FIELD(TCCR
, CSS
, 3, 2)
47 FIELD(TCCR
, TMRIS
, 7, 1)
50 #define CASCADING 0x03
54 static const int clkdiv
[] = {0, 1, 2, 8, 32, 64, 1024, 8192};
56 static uint8_t concat_reg(uint8_t *reg
)
58 return (reg
[0] << 8) | reg
[1];
61 static void update_events(RTMRState
*tmr
, int ch
)
63 uint16_t diff
[TMR_NR_EVENTS
], min
;
67 if (tmr
->tccr
[ch
] == 0) {
70 if (FIELD_EX8(tmr
->tccr
[ch
], TCCR
, CSS
) == 0) {
71 /* external clock mode */
72 /* event not happened */
75 if (FIELD_EX8(tmr
->tccr
[0], TCCR
, CSS
) == CASCADING
) {
81 diff
[cmia
] = concat_reg(tmr
->tcora
) - concat_reg(tmr
->tcnt
);
82 diff
[cmib
] = concat_reg(tmr
->tcorb
) - concat_reg(tmr
->tcnt
);
83 diff
[ovi
] = 0x10000 - concat_reg(tmr
->tcnt
);
86 diff
[cmia
] = tmr
->tcora
[ch
] - tmr
->tcnt
[ch
];
87 diff
[cmib
] = tmr
->tcorb
[ch
] - tmr
->tcnt
[ch
];
88 diff
[ovi
] = 0x100 - tmr
->tcnt
[ch
];
90 /* Search for the most recently occurring event. */
91 for (event
= 0, min
= diff
[0], i
= 1; i
< none
; i
++) {
97 tmr
->next
[ch
] = event
;
98 next_time
= diff
[event
];
99 next_time
*= clkdiv
[FIELD_EX8(tmr
->tccr
[ch
], TCCR
, CKS
)];
100 next_time
*= NANOSECONDS_PER_SECOND
;
101 next_time
/= tmr
->input_freq
;
102 next_time
+= qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL
);
103 timer_mod(&tmr
->timer
[ch
], next_time
);
106 static int elapsed_time(RTMRState
*tmr
, int ch
, int64_t delta
)
108 int divrate
= clkdiv
[FIELD_EX8(tmr
->tccr
[ch
], TCCR
, CKS
)];
111 tmr
->div_round
[ch
] += delta
;
113 et
= tmr
->div_round
[ch
] / divrate
;
114 tmr
->div_round
[ch
] %= divrate
;
116 /* disble clock. so no update */
122 static uint16_t read_tcnt(RTMRState
*tmr
, unsigned size
, int ch
)
124 int64_t delta
, now
= qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL
);
125 int elapsed
, ovf
= 0;
129 delta
= (now
- tmr
->tick
) * NANOSECONDS_PER_SECOND
/ tmr
->input_freq
;
133 if (FIELD_EX8(tmr
->tccr
[1], TCCR
, CSS
) == INTERNAL
) {
134 /* timer1 count update */
135 elapsed
= elapsed_time(tmr
, 1, delta
);
136 if (elapsed
>= 0x100) {
139 tcnt
[1] = tmr
->tcnt
[1] + (elapsed
& 0xff);
141 switch (FIELD_EX8(tmr
->tccr
[0], TCCR
, CSS
)) {
143 elapsed
= elapsed_time(tmr
, 0, delta
);
144 tcnt
[0] = tmr
->tcnt
[0] + elapsed
;
148 tcnt
[0] = tmr
->tcnt
[0] + ovf
;
153 tcnt
[0] = tmr
->tcnt
[0];
154 tcnt
[1] = tmr
->tcnt
[1];
160 ret
= deposit32(ret
, 0, 8, tcnt
[1]);
161 ret
= deposit32(ret
, 8, 8, tcnt
[0]);
166 static uint8_t read_tccr(uint8_t r
)
169 tccr
= FIELD_DP8(tccr
, TCCR
, TMRIS
,
170 FIELD_EX8(r
, TCCR
, TMRIS
));
171 tccr
= FIELD_DP8(tccr
, TCCR
, CSS
,
172 FIELD_EX8(r
, TCCR
, CSS
));
173 tccr
= FIELD_DP8(tccr
, TCCR
, CKS
,
174 FIELD_EX8(r
, TCCR
, CKS
));
178 static uint64_t tmr_read(void *opaque
, hwaddr addr
, unsigned size
)
180 RTMRState
*tmr
= opaque
;
184 if (size
== 2 && (ch
!= 0 || addr
== A_TCR
|| addr
== A_TCSR
)) {
185 qemu_log_mask(LOG_GUEST_ERROR
, "renesas_tmr: Invalid read size 0x%"
190 switch (addr
& 0x0e) {
193 ret
= FIELD_DP8(ret
, TCR
, CCLR
,
194 FIELD_EX8(tmr
->tcr
[ch
], TCR
, CCLR
));
195 ret
= FIELD_DP8(ret
, TCR
, OVIE
,
196 FIELD_EX8(tmr
->tcr
[ch
], TCR
, OVIE
));
197 ret
= FIELD_DP8(ret
, TCR
, CMIEA
,
198 FIELD_EX8(tmr
->tcr
[ch
], TCR
, CMIEA
));
199 ret
= FIELD_DP8(ret
, TCR
, CMIEB
,
200 FIELD_EX8(tmr
->tcr
[ch
], TCR
, CMIEB
));
204 ret
= FIELD_DP8(ret
, TCSR
, OSA
,
205 FIELD_EX8(tmr
->tcsr
[ch
], TCSR
, OSA
));
206 ret
= FIELD_DP8(ret
, TCSR
, OSB
,
207 FIELD_EX8(tmr
->tcsr
[ch
], TCSR
, OSB
));
210 ret
= FIELD_DP8(ret
, TCSR
, ADTE
,
211 FIELD_EX8(tmr
->tcsr
[ch
], TCSR
, ADTE
));
213 case 1: /* CH1 ADTE unimplement always 1 */
214 ret
= FIELD_DP8(ret
, TCSR
, ADTE
, 1);
220 return tmr
->tcora
[ch
];
221 } else if (ch
== 0) {
222 return concat_reg(tmr
->tcora
);
227 return tmr
->tcorb
[ch
];
229 return concat_reg(tmr
->tcorb
);
232 return read_tcnt(tmr
, size
, ch
);
235 return read_tccr(tmr
->tccr
[ch
]);
237 return read_tccr(tmr
->tccr
[0]) << 8 | read_tccr(tmr
->tccr
[1]);
240 qemu_log_mask(LOG_UNIMP
, "renesas_tmr: Register 0x%" HWADDR_PRIX
241 " not implemented\n",
248 static void tmr_write_count(RTMRState
*tmr
, int ch
, unsigned size
,
249 uint8_t *reg
, uint64_t val
)
253 update_events(tmr
, ch
);
255 reg
[0] = extract32(val
, 8, 8);
256 reg
[1] = extract32(val
, 0, 8);
257 update_events(tmr
, 0);
258 update_events(tmr
, 1);
262 static void tmr_write(void *opaque
, hwaddr addr
, uint64_t val
, unsigned size
)
264 RTMRState
*tmr
= opaque
;
267 if (size
== 2 && (ch
!= 0 || addr
== A_TCR
|| addr
== A_TCSR
)) {
268 qemu_log_mask(LOG_GUEST_ERROR
,
269 "renesas_tmr: Invalid write size 0x%" HWADDR_PRIX
"\n",
273 switch (addr
& 0x0e) {
281 tmr_write_count(tmr
, ch
, size
, tmr
->tcora
, val
);
284 tmr_write_count(tmr
, ch
, size
, tmr
->tcorb
, val
);
287 tmr_write_count(tmr
, ch
, size
, tmr
->tcnt
, val
);
290 tmr_write_count(tmr
, ch
, size
, tmr
->tccr
, val
);
293 qemu_log_mask(LOG_UNIMP
, "renesas_tmr: Register 0x%" HWADDR_PRIX
294 " not implemented\n",
300 static const MemoryRegionOps tmr_ops
= {
303 .endianness
= DEVICE_LITTLE_ENDIAN
,
305 .min_access_size
= 1,
306 .max_access_size
= 2,
309 .min_access_size
= 1,
310 .max_access_size
= 2,
314 static void timer_events(RTMRState
*tmr
, int ch
);
316 static uint16_t issue_event(RTMRState
*tmr
, int ch
, int sz
,
317 uint16_t tcnt
, uint16_t tcora
, uint16_t tcorb
)
321 switch (tmr
->next
[ch
]) {
326 if (FIELD_EX8(tmr
->tcr
[ch
], TCR
, CCLR
) == CCLR_A
) {
329 if (FIELD_EX8(tmr
->tcr
[ch
], TCR
, CMIEA
)) {
330 qemu_irq_pulse(tmr
->cmia
[ch
]);
332 if (sz
== 8 && ch
== 0 &&
333 FIELD_EX8(tmr
->tccr
[1], TCCR
, CSS
) == CASCADING
) {
335 timer_events(tmr
, 1);
341 if (FIELD_EX8(tmr
->tcr
[ch
], TCR
, CCLR
) == CCLR_B
) {
344 if (FIELD_EX8(tmr
->tcr
[ch
], TCR
, CMIEB
)) {
345 qemu_irq_pulse(tmr
->cmib
[ch
]);
350 if ((tcnt
>= (1 << sz
)) && FIELD_EX8(tmr
->tcr
[ch
], TCR
, OVIE
)) {
351 qemu_irq_pulse(tmr
->ovi
[ch
]);
355 g_assert_not_reached();
360 static void timer_events(RTMRState
*tmr
, int ch
)
364 tmr
->tcnt
[ch
] = read_tcnt(tmr
, 1, ch
);
365 if (FIELD_EX8(tmr
->tccr
[0], TCCR
, CSS
) != CASCADING
) {
366 tmr
->tcnt
[ch
] = issue_event(tmr
, ch
, 8,
369 tmr
->tcorb
[ch
]) & 0xff;
374 tcnt
= issue_event(tmr
, ch
, 16,
375 concat_reg(tmr
->tcnt
),
376 concat_reg(tmr
->tcora
),
377 concat_reg(tmr
->tcorb
));
378 tmr
->tcnt
[0] = (tcnt
>> 8) & 0xff;
379 tmr
->tcnt
[1] = tcnt
& 0xff;
381 update_events(tmr
, ch
);
384 static void timer_event0(void *opaque
)
386 RTMRState
*tmr
= opaque
;
388 timer_events(tmr
, 0);
391 static void timer_event1(void *opaque
)
393 RTMRState
*tmr
= opaque
;
395 timer_events(tmr
, 1);
398 static void rtmr_reset(DeviceState
*dev
)
400 RTMRState
*tmr
= RTMR(dev
);
401 tmr
->tcr
[0] = tmr
->tcr
[1] = 0x00;
404 tmr
->tcnt
[0] = tmr
->tcnt
[1] = 0x00;
405 tmr
->tcora
[0] = tmr
->tcora
[1] = 0xff;
406 tmr
->tcorb
[0] = tmr
->tcorb
[1] = 0xff;
407 tmr
->tccr
[0] = tmr
->tccr
[1] = 0x00;
408 tmr
->next
[0] = tmr
->next
[1] = none
;
409 tmr
->tick
= qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL
);
412 static void rtmr_init(Object
*obj
)
414 SysBusDevice
*d
= SYS_BUS_DEVICE(obj
);
415 RTMRState
*tmr
= RTMR(obj
);
418 memory_region_init_io(&tmr
->memory
, OBJECT(tmr
), &tmr_ops
,
419 tmr
, "renesas-tmr", 0x10);
420 sysbus_init_mmio(d
, &tmr
->memory
);
422 for (i
= 0; i
< ARRAY_SIZE(tmr
->ovi
); i
++) {
423 sysbus_init_irq(d
, &tmr
->cmia
[i
]);
424 sysbus_init_irq(d
, &tmr
->cmib
[i
]);
425 sysbus_init_irq(d
, &tmr
->ovi
[i
]);
427 timer_init_ns(&tmr
->timer
[0], QEMU_CLOCK_VIRTUAL
, timer_event0
, tmr
);
428 timer_init_ns(&tmr
->timer
[1], QEMU_CLOCK_VIRTUAL
, timer_event1
, tmr
);
431 static const VMStateDescription vmstate_rtmr
= {
434 .minimum_version_id
= 1,
435 .fields
= (VMStateField
[]) {
436 VMSTATE_INT64(tick
, RTMRState
),
437 VMSTATE_UINT8_ARRAY(tcnt
, RTMRState
, TMR_CH
),
438 VMSTATE_UINT8_ARRAY(tcora
, RTMRState
, TMR_CH
),
439 VMSTATE_UINT8_ARRAY(tcorb
, RTMRState
, TMR_CH
),
440 VMSTATE_UINT8_ARRAY(tcr
, RTMRState
, TMR_CH
),
441 VMSTATE_UINT8_ARRAY(tccr
, RTMRState
, TMR_CH
),
442 VMSTATE_UINT8_ARRAY(tcor
, RTMRState
, TMR_CH
),
443 VMSTATE_UINT8_ARRAY(tcsr
, RTMRState
, TMR_CH
),
444 VMSTATE_INT64_ARRAY(div_round
, RTMRState
, TMR_CH
),
445 VMSTATE_UINT8_ARRAY(next
, RTMRState
, TMR_CH
),
446 VMSTATE_TIMER_ARRAY(timer
, RTMRState
, TMR_CH
),
447 VMSTATE_END_OF_LIST()
451 static Property rtmr_properties
[] = {
452 DEFINE_PROP_UINT64("input-freq", RTMRState
, input_freq
, 0),
453 DEFINE_PROP_END_OF_LIST(),
456 static void rtmr_class_init(ObjectClass
*klass
, void *data
)
458 DeviceClass
*dc
= DEVICE_CLASS(klass
);
460 dc
->vmsd
= &vmstate_rtmr
;
461 dc
->reset
= rtmr_reset
;
462 device_class_set_props(dc
, rtmr_properties
);
465 static const TypeInfo rtmr_info
= {
466 .name
= TYPE_RENESAS_TMR
,
467 .parent
= TYPE_SYS_BUS_DEVICE
,
468 .instance_size
= sizeof(RTMRState
),
469 .instance_init
= rtmr_init
,
470 .class_init
= rtmr_class_init
,
473 static void rtmr_register_types(void)
475 type_register_static(&rtmr_info
);
478 type_init(rtmr_register_types
)