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
);
226 return tmr
->tcorb
[ch
];
228 return concat_reg(tmr
->tcorb
);
231 return read_tcnt(tmr
, size
, ch
);
234 return read_tccr(tmr
->tccr
[ch
]);
236 return read_tccr(tmr
->tccr
[0]) << 8 | read_tccr(tmr
->tccr
[1]);
239 qemu_log_mask(LOG_UNIMP
, "renesas_tmr: Register 0x%" HWADDR_PRIX
240 " not implemented\n",
247 static void tmr_write_count(RTMRState
*tmr
, int ch
, unsigned size
,
248 uint8_t *reg
, uint64_t val
)
252 update_events(tmr
, ch
);
254 reg
[0] = extract32(val
, 8, 8);
255 reg
[1] = extract32(val
, 0, 8);
256 update_events(tmr
, 0);
257 update_events(tmr
, 1);
261 static void tmr_write(void *opaque
, hwaddr addr
, uint64_t val
, unsigned size
)
263 RTMRState
*tmr
= opaque
;
266 if (size
== 2 && (ch
!= 0 || addr
== A_TCR
|| addr
== A_TCSR
)) {
267 qemu_log_mask(LOG_GUEST_ERROR
,
268 "renesas_tmr: Invalid write size 0x%" HWADDR_PRIX
"\n",
272 switch (addr
& 0x0e) {
280 tmr_write_count(tmr
, ch
, size
, tmr
->tcora
, val
);
283 tmr_write_count(tmr
, ch
, size
, tmr
->tcorb
, val
);
286 tmr_write_count(tmr
, ch
, size
, tmr
->tcnt
, val
);
289 tmr_write_count(tmr
, ch
, size
, tmr
->tccr
, val
);
292 qemu_log_mask(LOG_UNIMP
, "renesas_tmr: Register 0x%" HWADDR_PRIX
293 " not implemented\n",
299 static const MemoryRegionOps tmr_ops
= {
302 .endianness
= DEVICE_LITTLE_ENDIAN
,
304 .min_access_size
= 1,
305 .max_access_size
= 2,
308 .min_access_size
= 1,
309 .max_access_size
= 2,
313 static void timer_events(RTMRState
*tmr
, int ch
);
315 static uint16_t issue_event(RTMRState
*tmr
, int ch
, int sz
,
316 uint16_t tcnt
, uint16_t tcora
, uint16_t tcorb
)
320 switch (tmr
->next
[ch
]) {
325 if (FIELD_EX8(tmr
->tcr
[ch
], TCR
, CCLR
) == CCLR_A
) {
328 if (FIELD_EX8(tmr
->tcr
[ch
], TCR
, CMIEA
)) {
329 qemu_irq_pulse(tmr
->cmia
[ch
]);
331 if (sz
== 8 && ch
== 0 &&
332 FIELD_EX8(tmr
->tccr
[1], TCCR
, CSS
) == CASCADING
) {
334 timer_events(tmr
, 1);
340 if (FIELD_EX8(tmr
->tcr
[ch
], TCR
, CCLR
) == CCLR_B
) {
343 if (FIELD_EX8(tmr
->tcr
[ch
], TCR
, CMIEB
)) {
344 qemu_irq_pulse(tmr
->cmib
[ch
]);
349 if ((tcnt
>= (1 << sz
)) && FIELD_EX8(tmr
->tcr
[ch
], TCR
, OVIE
)) {
350 qemu_irq_pulse(tmr
->ovi
[ch
]);
354 g_assert_not_reached();
359 static void timer_events(RTMRState
*tmr
, int ch
)
363 tmr
->tcnt
[ch
] = read_tcnt(tmr
, 1, ch
);
364 if (FIELD_EX8(tmr
->tccr
[0], TCCR
, CSS
) != CASCADING
) {
365 tmr
->tcnt
[ch
] = issue_event(tmr
, ch
, 8,
368 tmr
->tcorb
[ch
]) & 0xff;
373 tcnt
= issue_event(tmr
, ch
, 16,
374 concat_reg(tmr
->tcnt
),
375 concat_reg(tmr
->tcora
),
376 concat_reg(tmr
->tcorb
));
377 tmr
->tcnt
[0] = (tcnt
>> 8) & 0xff;
378 tmr
->tcnt
[1] = tcnt
& 0xff;
380 update_events(tmr
, ch
);
383 static void timer_event0(void *opaque
)
385 RTMRState
*tmr
= opaque
;
387 timer_events(tmr
, 0);
390 static void timer_event1(void *opaque
)
392 RTMRState
*tmr
= opaque
;
394 timer_events(tmr
, 1);
397 static void rtmr_reset(DeviceState
*dev
)
399 RTMRState
*tmr
= RTMR(dev
);
400 tmr
->tcr
[0] = tmr
->tcr
[1] = 0x00;
403 tmr
->tcnt
[0] = tmr
->tcnt
[1] = 0x00;
404 tmr
->tcora
[0] = tmr
->tcora
[1] = 0xff;
405 tmr
->tcorb
[0] = tmr
->tcorb
[1] = 0xff;
406 tmr
->tccr
[0] = tmr
->tccr
[1] = 0x00;
407 tmr
->next
[0] = tmr
->next
[1] = none
;
408 tmr
->tick
= qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL
);
411 static void rtmr_init(Object
*obj
)
413 SysBusDevice
*d
= SYS_BUS_DEVICE(obj
);
414 RTMRState
*tmr
= RTMR(obj
);
417 memory_region_init_io(&tmr
->memory
, OBJECT(tmr
), &tmr_ops
,
418 tmr
, "renesas-tmr", 0x10);
419 sysbus_init_mmio(d
, &tmr
->memory
);
421 for (i
= 0; i
< ARRAY_SIZE(tmr
->ovi
); i
++) {
422 sysbus_init_irq(d
, &tmr
->cmia
[i
]);
423 sysbus_init_irq(d
, &tmr
->cmib
[i
]);
424 sysbus_init_irq(d
, &tmr
->ovi
[i
]);
426 timer_init_ns(&tmr
->timer
[0], QEMU_CLOCK_VIRTUAL
, timer_event0
, tmr
);
427 timer_init_ns(&tmr
->timer
[1], QEMU_CLOCK_VIRTUAL
, timer_event1
, tmr
);
430 static const VMStateDescription vmstate_rtmr
= {
433 .minimum_version_id
= 1,
434 .fields
= (VMStateField
[]) {
435 VMSTATE_INT64(tick
, RTMRState
),
436 VMSTATE_UINT8_ARRAY(tcnt
, RTMRState
, TMR_CH
),
437 VMSTATE_UINT8_ARRAY(tcora
, RTMRState
, TMR_CH
),
438 VMSTATE_UINT8_ARRAY(tcorb
, RTMRState
, TMR_CH
),
439 VMSTATE_UINT8_ARRAY(tcr
, RTMRState
, TMR_CH
),
440 VMSTATE_UINT8_ARRAY(tccr
, RTMRState
, TMR_CH
),
441 VMSTATE_UINT8_ARRAY(tcor
, RTMRState
, TMR_CH
),
442 VMSTATE_UINT8_ARRAY(tcsr
, RTMRState
, TMR_CH
),
443 VMSTATE_INT64_ARRAY(div_round
, RTMRState
, TMR_CH
),
444 VMSTATE_UINT8_ARRAY(next
, RTMRState
, TMR_CH
),
445 VMSTATE_TIMER_ARRAY(timer
, RTMRState
, TMR_CH
),
446 VMSTATE_END_OF_LIST()
450 static Property rtmr_properties
[] = {
451 DEFINE_PROP_UINT64("input-freq", RTMRState
, input_freq
, 0),
452 DEFINE_PROP_END_OF_LIST(),
455 static void rtmr_class_init(ObjectClass
*klass
, void *data
)
457 DeviceClass
*dc
= DEVICE_CLASS(klass
);
459 dc
->vmsd
= &vmstate_rtmr
;
460 dc
->reset
= rtmr_reset
;
461 device_class_set_props(dc
, rtmr_properties
);
464 static const TypeInfo rtmr_info
= {
465 .name
= TYPE_RENESAS_TMR
,
466 .parent
= TYPE_SYS_BUS_DEVICE
,
467 .instance_size
= sizeof(RTMRState
),
468 .instance_init
= rtmr_init
,
469 .class_init
= rtmr_class_init
,
472 static void rtmr_register_types(void)
474 type_register_static(&rtmr_info
);
477 type_init(rtmr_register_types
)