1 /* 2 * Renesas 8bit timer 3 * 4 * Datasheet: RX62N Group, RX621 Group User's Manual: Hardware 5 * (Rev.1.40 R01UH0033EJ0140) 6 * 7 * Copyright (c) 2019 Yoshinori Sato 8 * 9 * SPDX-License-Identifier: GPL-2.0-or-later 10 * 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. 14 * 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 18 * more details. 19 * 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/>. 22 */ 23 24 #include "qemu/osdep.h" 25 #include "qemu/log.h" 26 #include "hw/irq.h" 27 #include "hw/registerfields.h" 28 #include "hw/qdev-properties.h" 29 #include "hw/timer/renesas_tmr.h" 30 #include "migration/vmstate.h" 31 32 REG8(TCR, 0) 33 FIELD(TCR, CCLR, 3, 2) 34 FIELD(TCR, OVIE, 5, 1) 35 FIELD(TCR, CMIEA, 6, 1) 36 FIELD(TCR, CMIEB, 7, 1) 37 REG8(TCSR, 2) 38 FIELD(TCSR, OSA, 0, 2) 39 FIELD(TCSR, OSB, 2, 2) 40 FIELD(TCSR, ADTE, 4, 2) 41 REG8(TCORA, 4) 42 REG8(TCORB, 6) 43 REG8(TCNT, 8) 44 REG8(TCCR, 10) 45 FIELD(TCCR, CKS, 0, 3) 46 FIELD(TCCR, CSS, 3, 2) 47 FIELD(TCCR, TMRIS, 7, 1) 48 49 #define CSS_EXTERNAL 0x00 50 #define CSS_INTERNAL 0x01 51 #define CSS_INVALID 0x02 52 #define CSS_CASCADING 0x03 53 #define CCLR_A 0x01 54 #define CCLR_B 0x02 55 56 static const int clkdiv[] = {0, 1, 2, 8, 32, 64, 1024, 8192}; 57 58 static uint8_t concat_reg(uint8_t *reg) 59 { 60 return (reg[0] << 8) | reg[1]; 61 } 62 63 static void update_events(RTMRState *tmr, int ch) 64 { 65 uint16_t diff[TMR_NR_EVENTS], min; 66 int64_t next_time; 67 int i, event; 68 69 if (tmr->tccr[ch] == 0) { 70 return ; 71 } 72 if (FIELD_EX8(tmr->tccr[ch], TCCR, CSS) == 0) { 73 /* external clock mode */ 74 /* event not happened */ 75 return ; 76 } 77 if (FIELD_EX8(tmr->tccr[0], TCCR, CSS) == CSS_CASCADING) { 78 /* cascading mode */ 79 if (ch == 1) { 80 tmr->next[ch] = none; 81 return ; 82 } 83 diff[cmia] = concat_reg(tmr->tcora) - concat_reg(tmr->tcnt); 84 diff[cmib] = concat_reg(tmr->tcorb) - concat_reg(tmr->tcnt); 85 diff[ovi] = 0x10000 - concat_reg(tmr->tcnt); 86 } else { 87 /* separate mode */ 88 diff[cmia] = tmr->tcora[ch] - tmr->tcnt[ch]; 89 diff[cmib] = tmr->tcorb[ch] - tmr->tcnt[ch]; 90 diff[ovi] = 0x100 - tmr->tcnt[ch]; 91 } 92 /* Search for the most recently occurring event. */ 93 for (event = 0, min = diff[0], i = 1; i < none; i++) { 94 if (min > diff[i]) { 95 event = i; 96 min = diff[i]; 97 } 98 } 99 tmr->next[ch] = event; 100 next_time = diff[event]; 101 next_time *= clkdiv[FIELD_EX8(tmr->tccr[ch], TCCR, CKS)]; 102 next_time *= NANOSECONDS_PER_SECOND; 103 next_time /= tmr->input_freq; 104 next_time += qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); 105 timer_mod(&tmr->timer[ch], next_time); 106 } 107 108 static int elapsed_time(RTMRState *tmr, int ch, int64_t delta) 109 { 110 int divrate = clkdiv[FIELD_EX8(tmr->tccr[ch], TCCR, CKS)]; 111 int et; 112 113 tmr->div_round[ch] += delta; 114 if (divrate > 0) { 115 et = tmr->div_round[ch] / divrate; 116 tmr->div_round[ch] %= divrate; 117 } else { 118 /* disble clock. so no update */ 119 et = 0; 120 } 121 return et; 122 } 123 124 static uint16_t read_tcnt(RTMRState *tmr, unsigned size, int ch) 125 { 126 int64_t delta, now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); 127 int elapsed, ovf = 0; 128 uint16_t tcnt[2]; 129 uint32_t ret; 130 131 delta = (now - tmr->tick) * NANOSECONDS_PER_SECOND / tmr->input_freq; 132 if (delta > 0) { 133 tmr->tick = now; 134 135 switch (FIELD_EX8(tmr->tccr[1], TCCR, CSS)) { 136 case CSS_INTERNAL: 137 /* timer1 count update */ 138 elapsed = elapsed_time(tmr, 1, delta); 139 if (elapsed >= 0x100) { 140 ovf = elapsed >> 8; 141 } 142 tcnt[1] = tmr->tcnt[1] + (elapsed & 0xff); 143 break; 144 case CSS_INVALID: /* guest error to have set this */ 145 case CSS_EXTERNAL: /* QEMU doesn't implement these */ 146 case CSS_CASCADING: 147 tcnt[1] = tmr->tcnt[1]; 148 break; 149 } 150 switch (FIELD_EX8(tmr->tccr[0], TCCR, CSS)) { 151 case CSS_INTERNAL: 152 elapsed = elapsed_time(tmr, 0, delta); 153 tcnt[0] = tmr->tcnt[0] + elapsed; 154 break; 155 case CSS_CASCADING: 156 tcnt[0] = tmr->tcnt[0] + ovf; 157 break; 158 case CSS_INVALID: /* guest error to have set this */ 159 case CSS_EXTERNAL: /* QEMU doesn't implement this */ 160 tcnt[0] = tmr->tcnt[0]; 161 break; 162 } 163 } else { 164 tcnt[0] = tmr->tcnt[0]; 165 tcnt[1] = tmr->tcnt[1]; 166 } 167 if (size == 1) { 168 return tcnt[ch]; 169 } else { 170 ret = 0; 171 ret = deposit32(ret, 0, 8, tcnt[1]); 172 ret = deposit32(ret, 8, 8, tcnt[0]); 173 return ret; 174 } 175 } 176 177 static uint8_t read_tccr(uint8_t r) 178 { 179 uint8_t tccr = 0; 180 tccr = FIELD_DP8(tccr, TCCR, TMRIS, 181 FIELD_EX8(r, TCCR, TMRIS)); 182 tccr = FIELD_DP8(tccr, TCCR, CSS, 183 FIELD_EX8(r, TCCR, CSS)); 184 tccr = FIELD_DP8(tccr, TCCR, CKS, 185 FIELD_EX8(r, TCCR, CKS)); 186 return tccr; 187 } 188 189 static uint64_t tmr_read(void *opaque, hwaddr addr, unsigned size) 190 { 191 RTMRState *tmr = opaque; 192 int ch = addr & 1; 193 uint64_t ret; 194 195 if (size == 2 && (ch != 0 || addr == A_TCR || addr == A_TCSR)) { 196 qemu_log_mask(LOG_GUEST_ERROR, "renesas_tmr: Invalid read size 0x%" 197 HWADDR_PRIX "\n", 198 addr); 199 return UINT64_MAX; 200 } 201 switch (addr & 0x0e) { 202 case A_TCR: 203 ret = 0; 204 ret = FIELD_DP8(ret, TCR, CCLR, 205 FIELD_EX8(tmr->tcr[ch], TCR, CCLR)); 206 ret = FIELD_DP8(ret, TCR, OVIE, 207 FIELD_EX8(tmr->tcr[ch], TCR, OVIE)); 208 ret = FIELD_DP8(ret, TCR, CMIEA, 209 FIELD_EX8(tmr->tcr[ch], TCR, CMIEA)); 210 ret = FIELD_DP8(ret, TCR, CMIEB, 211 FIELD_EX8(tmr->tcr[ch], TCR, CMIEB)); 212 return ret; 213 case A_TCSR: 214 ret = 0; 215 ret = FIELD_DP8(ret, TCSR, OSA, 216 FIELD_EX8(tmr->tcsr[ch], TCSR, OSA)); 217 ret = FIELD_DP8(ret, TCSR, OSB, 218 FIELD_EX8(tmr->tcsr[ch], TCSR, OSB)); 219 switch (ch) { 220 case 0: 221 ret = FIELD_DP8(ret, TCSR, ADTE, 222 FIELD_EX8(tmr->tcsr[ch], TCSR, ADTE)); 223 break; 224 case 1: /* CH1 ADTE unimplement always 1 */ 225 ret = FIELD_DP8(ret, TCSR, ADTE, 1); 226 break; 227 } 228 return ret; 229 case A_TCORA: 230 if (size == 1) { 231 return tmr->tcora[ch]; 232 } else if (ch == 0) { 233 return concat_reg(tmr->tcora); 234 } 235 /* fall through */ 236 case A_TCORB: 237 if (size == 1) { 238 return tmr->tcorb[ch]; 239 } else { 240 return concat_reg(tmr->tcorb); 241 } 242 case A_TCNT: 243 return read_tcnt(tmr, size, ch); 244 case A_TCCR: 245 if (size == 1) { 246 return read_tccr(tmr->tccr[ch]); 247 } else { 248 return read_tccr(tmr->tccr[0]) << 8 | read_tccr(tmr->tccr[1]); 249 } 250 default: 251 qemu_log_mask(LOG_UNIMP, "renesas_tmr: Register 0x%" HWADDR_PRIX 252 " not implemented\n", 253 addr); 254 break; 255 } 256 return UINT64_MAX; 257 } 258 259 static void tmr_write_count(RTMRState *tmr, int ch, unsigned size, 260 uint8_t *reg, uint64_t val) 261 { 262 if (size == 1) { 263 reg[ch] = val; 264 update_events(tmr, ch); 265 } else { 266 reg[0] = extract32(val, 8, 8); 267 reg[1] = extract32(val, 0, 8); 268 update_events(tmr, 0); 269 update_events(tmr, 1); 270 } 271 } 272 273 static void tmr_write(void *opaque, hwaddr addr, uint64_t val, unsigned size) 274 { 275 RTMRState *tmr = opaque; 276 int ch = addr & 1; 277 278 if (size == 2 && (ch != 0 || addr == A_TCR || addr == A_TCSR)) { 279 qemu_log_mask(LOG_GUEST_ERROR, 280 "renesas_tmr: Invalid write size 0x%" HWADDR_PRIX "\n", 281 addr); 282 return; 283 } 284 switch (addr & 0x0e) { 285 case A_TCR: 286 tmr->tcr[ch] = val; 287 break; 288 case A_TCSR: 289 tmr->tcsr[ch] = val; 290 break; 291 case A_TCORA: 292 tmr_write_count(tmr, ch, size, tmr->tcora, val); 293 break; 294 case A_TCORB: 295 tmr_write_count(tmr, ch, size, tmr->tcorb, val); 296 break; 297 case A_TCNT: 298 tmr_write_count(tmr, ch, size, tmr->tcnt, val); 299 break; 300 case A_TCCR: 301 tmr_write_count(tmr, ch, size, tmr->tccr, val); 302 break; 303 default: 304 qemu_log_mask(LOG_UNIMP, "renesas_tmr: Register 0x%" HWADDR_PRIX 305 " not implemented\n", 306 addr); 307 break; 308 } 309 } 310 311 static const MemoryRegionOps tmr_ops = { 312 .write = tmr_write, 313 .read = tmr_read, 314 .endianness = DEVICE_LITTLE_ENDIAN, 315 .impl = { 316 .min_access_size = 1, 317 .max_access_size = 2, 318 }, 319 .valid = { 320 .min_access_size = 1, 321 .max_access_size = 2, 322 }, 323 }; 324 325 static void timer_events(RTMRState *tmr, int ch); 326 327 static uint16_t issue_event(RTMRState *tmr, int ch, int sz, 328 uint16_t tcnt, uint16_t tcora, uint16_t tcorb) 329 { 330 uint16_t ret = tcnt; 331 332 switch (tmr->next[ch]) { 333 case none: 334 break; 335 case cmia: 336 if (tcnt >= tcora) { 337 if (FIELD_EX8(tmr->tcr[ch], TCR, CCLR) == CCLR_A) { 338 ret = tcnt - tcora; 339 } 340 if (FIELD_EX8(tmr->tcr[ch], TCR, CMIEA)) { 341 qemu_irq_pulse(tmr->cmia[ch]); 342 } 343 if (sz == 8 && ch == 0 && 344 FIELD_EX8(tmr->tccr[1], TCCR, CSS) == CSS_CASCADING) { 345 tmr->tcnt[1]++; 346 timer_events(tmr, 1); 347 } 348 } 349 break; 350 case cmib: 351 if (tcnt >= tcorb) { 352 if (FIELD_EX8(tmr->tcr[ch], TCR, CCLR) == CCLR_B) { 353 ret = tcnt - tcorb; 354 } 355 if (FIELD_EX8(tmr->tcr[ch], TCR, CMIEB)) { 356 qemu_irq_pulse(tmr->cmib[ch]); 357 } 358 } 359 break; 360 case ovi: 361 if ((tcnt >= (1 << sz)) && FIELD_EX8(tmr->tcr[ch], TCR, OVIE)) { 362 qemu_irq_pulse(tmr->ovi[ch]); 363 } 364 break; 365 default: 366 g_assert_not_reached(); 367 } 368 return ret; 369 } 370 371 static void timer_events(RTMRState *tmr, int ch) 372 { 373 uint16_t tcnt; 374 375 tmr->tcnt[ch] = read_tcnt(tmr, 1, ch); 376 if (FIELD_EX8(tmr->tccr[0], TCCR, CSS) != CSS_CASCADING) { 377 tmr->tcnt[ch] = issue_event(tmr, ch, 8, 378 tmr->tcnt[ch], 379 tmr->tcora[ch], 380 tmr->tcorb[ch]) & 0xff; 381 } else { 382 if (ch == 1) { 383 return ; 384 } 385 tcnt = issue_event(tmr, ch, 16, 386 concat_reg(tmr->tcnt), 387 concat_reg(tmr->tcora), 388 concat_reg(tmr->tcorb)); 389 tmr->tcnt[0] = (tcnt >> 8) & 0xff; 390 tmr->tcnt[1] = tcnt & 0xff; 391 } 392 update_events(tmr, ch); 393 } 394 395 static void timer_event0(void *opaque) 396 { 397 RTMRState *tmr = opaque; 398 399 timer_events(tmr, 0); 400 } 401 402 static void timer_event1(void *opaque) 403 { 404 RTMRState *tmr = opaque; 405 406 timer_events(tmr, 1); 407 } 408 409 static void rtmr_reset(DeviceState *dev) 410 { 411 RTMRState *tmr = RTMR(dev); 412 tmr->tcr[0] = tmr->tcr[1] = 0x00; 413 tmr->tcsr[0] = 0x00; 414 tmr->tcsr[1] = 0x10; 415 tmr->tcnt[0] = tmr->tcnt[1] = 0x00; 416 tmr->tcora[0] = tmr->tcora[1] = 0xff; 417 tmr->tcorb[0] = tmr->tcorb[1] = 0xff; 418 tmr->tccr[0] = tmr->tccr[1] = 0x00; 419 tmr->next[0] = tmr->next[1] = none; 420 tmr->tick = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); 421 } 422 423 static void rtmr_init(Object *obj) 424 { 425 SysBusDevice *d = SYS_BUS_DEVICE(obj); 426 RTMRState *tmr = RTMR(obj); 427 int i; 428 429 memory_region_init_io(&tmr->memory, OBJECT(tmr), &tmr_ops, 430 tmr, "renesas-tmr", 0x10); 431 sysbus_init_mmio(d, &tmr->memory); 432 433 for (i = 0; i < ARRAY_SIZE(tmr->ovi); i++) { 434 sysbus_init_irq(d, &tmr->cmia[i]); 435 sysbus_init_irq(d, &tmr->cmib[i]); 436 sysbus_init_irq(d, &tmr->ovi[i]); 437 } 438 timer_init_ns(&tmr->timer[0], QEMU_CLOCK_VIRTUAL, timer_event0, tmr); 439 timer_init_ns(&tmr->timer[1], QEMU_CLOCK_VIRTUAL, timer_event1, tmr); 440 } 441 442 static const VMStateDescription vmstate_rtmr = { 443 .name = "rx-tmr", 444 .version_id = 1, 445 .minimum_version_id = 1, 446 .fields = (VMStateField[]) { 447 VMSTATE_INT64(tick, RTMRState), 448 VMSTATE_UINT8_ARRAY(tcnt, RTMRState, TMR_CH), 449 VMSTATE_UINT8_ARRAY(tcora, RTMRState, TMR_CH), 450 VMSTATE_UINT8_ARRAY(tcorb, RTMRState, TMR_CH), 451 VMSTATE_UINT8_ARRAY(tcr, RTMRState, TMR_CH), 452 VMSTATE_UINT8_ARRAY(tccr, RTMRState, TMR_CH), 453 VMSTATE_UINT8_ARRAY(tcor, RTMRState, TMR_CH), 454 VMSTATE_UINT8_ARRAY(tcsr, RTMRState, TMR_CH), 455 VMSTATE_INT64_ARRAY(div_round, RTMRState, TMR_CH), 456 VMSTATE_UINT8_ARRAY(next, RTMRState, TMR_CH), 457 VMSTATE_TIMER_ARRAY(timer, RTMRState, TMR_CH), 458 VMSTATE_END_OF_LIST() 459 } 460 }; 461 462 static Property rtmr_properties[] = { 463 DEFINE_PROP_UINT64("input-freq", RTMRState, input_freq, 0), 464 DEFINE_PROP_END_OF_LIST(), 465 }; 466 467 static void rtmr_class_init(ObjectClass *klass, void *data) 468 { 469 DeviceClass *dc = DEVICE_CLASS(klass); 470 471 dc->vmsd = &vmstate_rtmr; 472 dc->reset = rtmr_reset; 473 device_class_set_props(dc, rtmr_properties); 474 } 475 476 static const TypeInfo rtmr_info = { 477 .name = TYPE_RENESAS_TMR, 478 .parent = TYPE_SYS_BUS_DEVICE, 479 .instance_size = sizeof(RTMRState), 480 .instance_init = rtmr_init, 481 .class_init = rtmr_class_init, 482 }; 483 484 static void rtmr_register_types(void) 485 { 486 type_register_static(&rtmr_info); 487 } 488 489 type_init(rtmr_register_types) 490