2
0

renesas_tmr.c 14 KB

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