• R/O
  • HTTP
  • SSH
  • HTTPS

Commit

Tags
No Tags

Frequently used words (click to add to your profile)

javac++androidlinuxc#windowsobjective-ccocoa誰得qtpythonphprubygameguibathyscaphec計画中(planning stage)翻訳omegatframeworktwitterdomtestvb.netdirectxゲームエンジンbtronarduinopreviewer

Commit MetaInfo

Revision83d3a09666280b97536484d34a9ec7f275613d44 (tree)
Time2020-06-01 00:49:33
AuthorYoshinori Sato <ysato@user...>
CommiterYoshinori Sato

Log Message

hw/char: Renesas SCI module.

This module supported SCI / SCIa / SCIF.

Hardware manual.
SCI / SCIF
https://www.renesas.com/us/en/doc/products/mpumcu/001/r01uh0457ej0401_sh7751.pdf
SCIa
https://www.renesas.com/us/en/doc/products/mpumcu/doc/rx_family/r01uh0033ej0140_rx62n.pdf

Signed-off-by: Yoshinori Sato <ysato@users.sourceforge.jp>

Change Summary

Incremental Difference

--- a/hw/char/Kconfig
+++ b/hw/char/Kconfig
@@ -46,3 +46,6 @@ config SCLPCONSOLE
4646
4747 config TERMINAL3270
4848 bool
49+
50+config RENESAS_SCI
51+ bool
--- a/hw/char/Makefile.objs
+++ b/hw/char/Makefile.objs
@@ -16,7 +16,6 @@ common-obj-$(CONFIG_CADENCE) += cadence_uart.o
1616 common-obj-$(CONFIG_EXYNOS4) += exynos4210_uart.o
1717 common-obj-$(CONFIG_COLDFIRE) += mcf_uart.o
1818 common-obj-$(CONFIG_OMAP) += omap_uart.o
19-common-obj-$(CONFIG_SH4) += sh_serial.o
2019 common-obj-$(CONFIG_DIGIC) += digic-uart.o
2120 common-obj-$(CONFIG_STM32F2XX_USART) += stm32f2xx_usart.o
2221 common-obj-$(CONFIG_RASPI) += bcm2835_aux.o
@@ -31,6 +30,8 @@ common-obj-$(CONFIG_LM32) += lm32_uart.o
3130 common-obj-$(CONFIG_MILKYMIST) += milkymist-uart.o
3231 common-obj-$(CONFIG_SCLPCONSOLE) += sclpconsole.o sclpconsole-lm.o
3332
33+common-obj-$(CONFIG_RENESAS_SCI) += renesas_sci.o
34+
3435 obj-$(CONFIG_VIRTIO) += virtio-serial-bus.o
3536 obj-$(CONFIG_PSERIES) += spapr_vty.o
3637 obj-$(CONFIG_TERMINAL3270) += terminal3270.o
--- /dev/null
+++ b/hw/char/renesas_sci.c
@@ -0,0 +1,786 @@
1+/*
2+ * Renesas Serial Communication Interface (SCI / SCIa / SCIF)
3+ *
4+ * Datasheet: RX62N Group, RX621 Group User's Manual: Hardware
5+ * (Rev.1.40 R01UH0033EJ0140)
6+ * And SH7751 Group, SH7751R Group User's Manual: Hardware
7+ * (Rev.4.01 R01UH0457EJ0401)
8+ *
9+ * Copyright (c) 2020 Yoshinori Sato
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 "qapi/error.h"
27+#include "qemu-common.h"
28+#include "hw/hw.h"
29+#include "hw/irq.h"
30+#include "hw/sysbus.h"
31+#include "hw/registerfields.h"
32+#include "hw/qdev-properties.h"
33+#include "hw/char/renesas_sci.h"
34+#include "migration/vmstate.h"
35+#include "qemu/error-report.h"
36+
37+/* SCI register map */
38+REG8(SMR, 0)
39+ FIELD(SMR, CKS, 0, 2)
40+ FIELD(SMR, MP, 2, 1)
41+ FIELD(SMR, STOP, 3, 1)
42+ FIELD(SMR, PM, 4, 1)
43+ FIELD(SMR, PE, 5, 1)
44+ FIELD(SMR, CHR, 6, 1)
45+ FIELD(SMR, CM, 7, 1)
46+REG16(BRR, 2)
47+REG16(SCR, 4)
48+ FIELD(SCR, CKE, 0, 2)
49+ FIELD(SCR, TEIE, 2, 1)
50+ FIELD(SCR, MPIE, 3, 1)
51+ FIELD(SCR, REIE, 3, 1)
52+ FIELD(SCR, RE, 4, 1)
53+ FIELD(SCR, TE, 5, 1)
54+ FIELD(SCR, RIE, 6, 1)
55+ FIELD(SCR, TIE, 7, 1)
56+REG16(TDR, 6)
57+REG16(SSR, 8)
58+ FIELD(SSR, MPBT, 0, 1)
59+ FIELD(SSR, MPB, 1, 1)
60+ FIELD(SSR, TEND, 2, 1)
61+ FIELD(SSR, ERR, 3, 3)
62+ FIELD(SSR, PER, 3, 1)
63+ FIELD(SSR, FER, 4, 1)
64+ FIELD(SSR, ORER, 5, 1)
65+ FIELD(SSR, RDRF, 6, 1)
66+ FIELD(SSR, TDRE, 7, 1)
67+REG16(FSR, 8)
68+ FIELD(FSR, DR, 0, 1)
69+ FIELD(FSR, RDF, 1, 1)
70+ FIELD(FSR, RDF_DR, 0, 2)
71+ FIELD(FSR, PER, 2, 1)
72+ FIELD(FSR, FER, 3, 1)
73+ FIELD(FSR, BRK, 4, 1)
74+ FIELD(FSR, TDFE, 5, 1)
75+ FIELD(FSR, TEND, 6, 1)
76+ FIELD(FSR, ER, 7, 1)
77+ FIELD(FSR, FERn, 8, 4)
78+ FIELD(FSR, PERn, 12, 4)
79+REG16(RDR, 10)
80+REG16(SCMR, 12)
81+ FIELD(SCMR, SMIF, 0, 1)
82+ FIELD(SCMR, SINV, 2, 1)
83+ FIELD(SCMR, SDIR, 3, 1)
84+ FIELD(SCMR, BCP2, 7, 1)
85+REG16(FCR, 12)
86+ FIELD(FCR, LOOP, 0, 1)
87+ FIELD(FCR, RFRST, 1, 1)
88+ FIELD(FCR, TFRST, 2, 1)
89+ FIELD(FCR, MCE, 3, 1)
90+ FIELD(FCR, TTRG, 4, 2)
91+ FIELD(FCR, RTRG, 6, 2)
92+ FIELD(FCR, RSTRG, 8, 3)
93+REG16(SEMR, 14)
94+ FIELD(SEMR, ACS0, 0, 1)
95+ FIELD(SEMR, ABCS, 4, 1)
96+REG16(FDR, 14)
97+ FIELD(FDR, Rn, 0, 4)
98+ FIELD(FDR, Tn, 8, 4)
99+REG16(SPTR, 16)
100+ FIELD(SPTR, SPB2DT, 0, 1)
101+ FIELD(SPTR, SPB2IO, 1, 1)
102+ FIELD(SPTR, SCKDT, 2, 1)
103+ FIELD(SPTR, SCKIO, 3, 1)
104+ FIELD(SPTR, CTSDT, 4, 1)
105+ FIELD(SPTR, CTSIO, 5, 1)
106+ FIELD(SPTR, RTSDT, 6, 1)
107+ FIELD(SPTR, RTSIO, 7, 1)
108+ FIELD(SPTR, EIO, 7, 1)
109+REG16(LSR, 18)
110+ FIELD(LSR, ORER, 0, 1)
111+
112+#define SCIF_FIFO_DEPTH 16
113+#define IS_SCI(sci) (sci->feature < SCI_FEAT_SCIF)
114+#define IS_SCIA(sci) (IS_SCI(sci) && sci->feature >= SCI_FEAT_SCIA)
115+#define IS_SCIF(sci) (!IS_SCI(sci))
116+
117+static const int sci_rtrg[] = {1, 4, 8, 14};
118+
119+static void update_event_time(RSCIState *sci, int evt, int64_t t)
120+{
121+ if (t > 0) {
122+ t += qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
123+ sci->event[evt].time = t;
124+ if (timer_expire_time_ns(sci->event_timer) > t) {
125+ timer_mod(sci->event_timer, t);
126+ }
127+ } else {
128+ sci->event[evt].time = 0;
129+ }
130+}
131+
132+static int sci_is_rxi(RSCIState *sci)
133+{
134+ int eio;
135+ int enable;
136+ enable = FIELD_EX16(sci->scr, SCR, RIE);
137+ if (IS_SCI(sci)) {
138+ eio = (sci->feature != SCI_FEAT_SCI) ||
139+ (FIELD_EX16(sci->sptr, SPTR, EIO) == 0);
140+ return FIELD_EX16(sci->Xsr, SSR, RDRF) && enable && eio;
141+ } else {
142+ return (FIELD_EX16(sci->Xsr, FSR, RDF_DR) != 0) && enable;
143+ }
144+}
145+
146+static int sci_is_txi(RSCIState *sci)
147+{
148+ int enable = FIELD_EX16(sci->scr, SCR, TIE);
149+ if (IS_SCI(sci)) {
150+ return enable && FIELD_EX16(sci->Xsr, SSR, TDRE);
151+ } else {
152+ return enable && FIELD_EX16(sci->Xsr, FSR, TDFE);
153+ }
154+}
155+
156+static void sci_irq(RSCIState *sci, int req)
157+{
158+ int br;
159+ int irq;
160+ int rie;
161+
162+ switch (req) {
163+ case ERI:
164+ rie = FIELD_EX16(sci->scr, SCR, RIE);
165+ if (IS_SCI(sci)) {
166+ irq = rie && (FIELD_EX16(sci->Xsr, SSR, ERR) != 0);
167+ } else {
168+ irq = (rie || FIELD_EX16(sci->scr, SCR, REIE)) &&
169+ FIELD_EX16(sci->Xsr, FSR, ER);
170+ }
171+ qemu_set_irq(sci->irq[ERI], irq);
172+ break;
173+ case RXI:
174+ if (IS_SCIA(sci)) {
175+ if (sci_is_rxi(sci)) {
176+ qemu_irq_pulse(sci->irq[RXI]);
177+ }
178+ } else {
179+ qemu_set_irq(sci->irq[RXI], sci_is_rxi(sci));
180+ }
181+ break;
182+ case TXI:
183+ if (IS_SCIA(sci)) {
184+ if (sci_is_txi(sci)) {
185+ qemu_irq_pulse(sci->irq[TXI]);
186+ }
187+ } else {
188+ qemu_set_irq(sci->irq[TXI], sci_is_txi(sci));
189+ }
190+ break;
191+ case BRI: /* TEI */
192+ if (IS_SCI(sci)) {
193+ qemu_set_irq(sci->irq[TEI],
194+ FIELD_EX16(sci->Xsr, SSR, TEND) &&
195+ FIELD_EX16(sci->scr, SCR, TEIE));
196+ } else {
197+ rie = FIELD_EX16(sci->scr, SCR, RIE);
198+ br = (rie || FIELD_EX16(sci->scr, SCR, REIE)) &&
199+ FIELD_EX16(sci->Xsr, FSR, BRK);
200+ qemu_set_irq(sci->irq[BRI], br);
201+ }
202+ break;
203+ }
204+}
205+
206+static int can_receive(void *opaque)
207+{
208+ RSCIState *sci = RSCI(opaque);
209+ int fifo_free = 0;
210+ if (FIELD_EX16(sci->scr, SCR, RE)) {
211+ /* Receiver enabled */
212+ fifo_free = fifo8_num_free(&sci->rxfifo);
213+ if (IS_SCIF(sci) && fifo_free == 0) {
214+ /* FIFO overrun */
215+ sci->lsr = FIELD_DP16(sci->lsr, LSR, ORER, 1);
216+ sci_irq(sci, ERI);
217+ }
218+ }
219+ return fifo_free;
220+}
221+
222+static void sci_receive(void *opaque, const uint8_t *buf, int size)
223+{
224+ RSCIState *sci = RSCI(opaque);
225+ int rtrg;
226+
227+ fifo8_push_all(&sci->rxfifo, buf, size);
228+ if (sci->event[RXNEXT].time == 0) {
229+ if (IS_SCI(sci)) {
230+ sci->Xsr = FIELD_DP16(sci->Xsr, SSR, RDRF, 1);
231+ update_event_time(sci, RXNEXT, sci->trtime);
232+ } else {
233+ rtrg = sci_rtrg[FIELD_EX16(sci->fcr, FCR, RTRG)];
234+ if (fifo8_num_used(&sci->rxfifo) >= rtrg) {
235+ sci->Xsr = FIELD_DP16(sci->Xsr, FSR, RDF, 1);
236+ } else {
237+ update_event_time(sci, RXTOUT, 15 * sci->etu);
238+ }
239+ }
240+ sci_irq(sci, RXI);
241+ }
242+}
243+
244+static void sci_send_byte(RSCIState *sci)
245+{
246+ if (IS_SCI(sci)) {
247+ if (qemu_chr_fe_backend_connected(&sci->chr)) {
248+ qemu_chr_fe_write_all(&sci->chr, &sci->tdr, 1);
249+ }
250+ sci->Xsr = FIELD_DP16(sci->Xsr, SSR, TEND, 0);
251+ sci->Xsr = FIELD_DP16(sci->Xsr, SSR, TDRE, 1);
252+ }
253+}
254+
255+static int transmit_byte(RSCIState *sci)
256+{
257+ int64_t elapsed;
258+ int byte = 0;
259+ if (sci->tx_start_time > 0) {
260+ elapsed = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) - sci->tx_start_time;
261+ byte = elapsed / sci->trtime;
262+ if (byte > sci->tdcnt) {
263+ byte = sci->tdcnt;
264+ }
265+ }
266+ return byte;
267+}
268+
269+static int64_t sci_rx_timeout(RSCIState *sci)
270+{
271+ if (IS_SCIF(sci)) {
272+ sci->Xsr = FIELD_DP16(sci->Xsr, FSR, DR, 1);
273+ sci_irq(sci, RXI);
274+ }
275+ return 0;
276+}
277+
278+static int64_t sci_rx_next(RSCIState *sci)
279+{
280+ int64_t next_event = 0;
281+ if (IS_SCI(sci) && !fifo8_is_empty(&sci->rxfifo)) {
282+ if (FIELD_EX16(sci->Xsr, SSR, RDRF)) {
283+ /* Receiver overrun */
284+ sci->Xsr = FIELD_DP16(sci->Xsr, SSR, ORER, 1);
285+ sci_irq(sci, ERI);
286+ } else {
287+ /* Trigger next event */
288+ sci->Xsr = FIELD_DP16(sci->Xsr, SSR, RDRF, 1);
289+ sci_irq(sci, RXI);
290+ next_event = sci->trtime;
291+ }
292+ }
293+ return next_event;
294+}
295+
296+static int64_t sci_tx_empty(RSCIState *sci)
297+{
298+ int64_t ret = 0;
299+ if (IS_SCI(sci)) {
300+ if (!FIELD_EX16(sci->Xsr, SSR, TDRE)) {
301+ sci_send_byte(sci);
302+ ret = sci->trtime;
303+ sci_irq(sci, TXI);
304+ } else {
305+ sci->Xsr = FIELD_DP16(sci->Xsr, SSR, TEND, 1);
306+ sci_irq(sci, TEI);
307+ }
308+ } else {
309+ sci->tdcnt -= transmit_byte(sci);
310+ sci->Xsr = FIELD_DP16(sci->Xsr, FSR, TDFE, 1);
311+ sci_irq(sci, TXI);
312+ }
313+ return ret;
314+}
315+
316+static int64_t sci_tx_end(RSCIState *sci)
317+{
318+ if (IS_SCIF(sci)) {
319+ sci->tdcnt = 0;
320+ sci->Xsr = FIELD_DP16(sci->Xsr, FSR, TEND, 1);
321+ sci_irq(sci, TEI);
322+ }
323+ return 0;
324+}
325+
326+static void sci_timer_event(void *opaque)
327+{
328+ RSCIState *sci = RSCI(opaque);
329+ int64_t now, next, t;
330+ int i;
331+
332+ now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
333+ next = INT64_MAX;
334+ for (i = 0; i < NR_SCI_EVENT; i++) {
335+ if (sci->event[i].time > 0 && sci->event[i].time <= now) {
336+ t = sci->event[i].handler(sci);
337+ sci->event[i].time = (t > 0) ? now + t : 0;
338+ }
339+ if (sci->event[i].time > 0) {
340+ next = MIN(next, sci->event[i].time);
341+ }
342+ }
343+ if (next < INT64_MAX) {
344+ timer_mod(sci->event_timer, next);
345+ } else {
346+ timer_del(sci->event_timer);
347+ }
348+}
349+
350+static void update_trtime(RSCIState *sci)
351+{
352+ int divrate;
353+ if (IS_SCIA(sci)) {
354+ divrate = 16 * (2 - FIELD_EX8(sci->semr, SEMR, ABCS));
355+ } else {
356+ divrate = 32;
357+ }
358+
359+ /* x bit transmit time (divrate * brr) / base freq */
360+ sci->etu = divrate * 1 << (2 * FIELD_EX16(sci->smr, SMR, CKS));
361+ sci->etu *= sci->brr + 1;
362+ sci->etu *= NANOSECONDS_PER_SECOND;
363+ sci->etu /= sci->input_freq;
364+
365+ /* char per bits */
366+ sci->trtime = 8 - FIELD_EX16(sci->smr, SMR, CHR);
367+ sci->trtime += FIELD_EX16(sci->smr, SMR, PE);
368+ sci->trtime += FIELD_EX16(sci->smr, SMR, STOP) + 1 + 1;
369+ sci->trtime *= sci->etu;
370+}
371+
372+#define IS_TR_ENABLED(scr) \
373+ (FIELD_EX16(scr, SCR, TE) || FIELD_EX16(scr, SCR, RE))
374+
375+#define SCI_IS_NOT_SUPPORTED(sci, name) \
376+ if (sci->feature == SCI_FEAT_SCI) { \
377+ qemu_log_mask(LOG_GUEST_ERROR, \
378+ "reneas_sci: " #name " is not supported.\n"); \
379+ }
380+
381+static void sci_write(void *opaque, hwaddr addr, uint64_t val, unsigned size)
382+{
383+ RSCIState *sci = RSCI(opaque);
384+ int txtrg;
385+ int rxtrg;
386+ uint8_t txd;
387+ uint16_t ssr_mask;
388+ bool tx_start = false;
389+
390+ if (IS_SCI(sci)) {
391+ txtrg = 1;
392+ } else {
393+ txtrg = 1 << (3 - FIELD_EX16(sci->fcr, FCR, TTRG));
394+ }
395+ switch (sci->regsize) {
396+ case 8:
397+ addr <<= 1; break;
398+ case 32:
399+ addr >>= 1; break;
400+ }
401+ switch (addr) {
402+ case A_SMR:
403+ if (IS_SCIA(sci) && IS_TR_ENABLED(sci->scr)) {
404+ qemu_log_mask(LOG_GUEST_ERROR,
405+ "reneas_sci: SMR write protected.\n");
406+ break;
407+ }
408+ sci->smr = val;
409+ update_trtime(sci);
410+ break;
411+ case A_BRR:
412+ if (IS_SCIA(sci) && IS_TR_ENABLED(sci->scr)) {
413+ qemu_log_mask(LOG_GUEST_ERROR,
414+ "reneas_sci: BRR write protected.\n");
415+ break;
416+ }
417+ sci->brr = val;
418+ update_trtime(sci);
419+ break;
420+ case A_SCR:
421+ sci->scr = val;
422+ if (FIELD_EX16(sci->scr, SCR, TE)) {
423+ /* Transmitter enable */
424+ if (IS_SCI(sci)) {
425+ sci->Xsr = FIELD_DP16(sci->Xsr, SSR, TDRE, 1);
426+ sci->Xsr = FIELD_DP16(sci->Xsr, SSR, TEND, 1);
427+ } else {
428+ sci->Xsr = FIELD_DP16(sci->Xsr, FSR, TEND, 1);
429+ sci->Xsr = FIELD_DP16(sci->Xsr, FSR, TDFE, 1);
430+ sci->tx_start_time = 0;
431+ }
432+ sci_irq(sci, TXI);
433+ sci_irq(sci, TEI);
434+ } else {
435+ /* Transmitter disable */
436+ update_event_time(sci, TXEND, 0);
437+ update_event_time(sci, TXEMPTY, 0);
438+ }
439+ break;
440+ case A_TDR:
441+ if (IS_SCI(sci)) {
442+ sci->tdr = val;
443+ if (IS_SCIA(sci)) {
444+ if (FIELD_EX16(sci->Xsr, SSR, TEND)) {
445+ update_event_time(sci, TXEMPTY, sci->trtime);
446+ sci_send_byte(sci);
447+ } else {
448+ sci->Xsr = FIELD_DP16(sci->Xsr, SSR, TDRE, 0);
449+ }
450+ sci_irq(sci, TXI);
451+ sci_irq(sci, TEI);
452+ }
453+ } else {
454+ if (sci->tx_start_time > 0) {
455+ sci->tdcnt -= transmit_byte(sci);
456+ } else {
457+ sci->tx_start_time = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
458+ }
459+ if (sci->tdcnt >= SCIF_FIFO_DEPTH) {
460+ break;
461+ }
462+ txd = val;
463+ if (qemu_chr_fe_backend_connected(&sci->chr)) {
464+ qemu_chr_fe_write_all(&sci->chr, &txd, 1);
465+ }
466+ if (FIELD_EX16(sci->fcr, FCR, LOOP) && can_receive(sci) > 0) {
467+ /* Loopback mode */
468+ sci_receive(sci, &txd, 1);
469+ }
470+ sci->tdcnt++;
471+ sci->Xsr = FIELD_DP16(sci->Xsr, FSR, TEND, 0);
472+ update_event_time(sci, TXEND, sci->tdcnt);
473+ if (sci->tdcnt > txtrg) {
474+ sci->Xsr = FIELD_DP16(sci->Xsr, FSR, TDFE, 0);
475+ update_event_time(sci, TXEMPTY, sci->tdcnt - txtrg + 1);
476+ sci_irq(sci, TXI);
477+ }
478+ }
479+ break;
480+ case A_FSR: /* A_SSR */
481+ if (IS_SCI(sci)) {
482+ /* Mask for read only bits */
483+ ssr_mask = IS_SCIA(sci) ? 0xc7 : 0x07;
484+ sci->Xsr = FIELD_DP16(sci->Xsr, SSR, MPBT,
485+ FIELD_EX16(val, SSR, MPBT));
486+ sci->Xsr &= (val | ssr_mask);
487+ /* Clear ERI */
488+ sci_irq(sci, ERI);
489+ if (sci->feature == SCI_FEAT_SCI) {
490+ tx_start = FIELD_EX16(sci->read_Xsr, SSR, TDRE) &&
491+ !FIELD_EX16(sci->Xsr, SSR, TDRE) &&
492+ (FIELD_EX16(sci->Xsr, SSR, ERR) == 0);
493+ if (tx_start) {
494+ sci_send_byte(sci);
495+ update_event_time(sci, TXEMPTY, sci->trtime);
496+ sci_irq(sci, TXI);
497+ }
498+ }
499+ } else {
500+ rxtrg = sci_rtrg[FIELD_EX16(sci->fcr, FCR, RTRG)];
501+ ssr_mask = ~(sci->read_Xsr & 0xf3);
502+ sci->tdcnt -= transmit_byte(sci);
503+ if (sci->tdcnt < txtrg) {
504+ ssr_mask = FIELD_DP16(ssr_mask, FSR, TDFE, 1);
505+ }
506+ if (fifo8_num_used(&sci->rxfifo) >= rxtrg) {
507+ ssr_mask = FIELD_DP16(ssr_mask, FSR, RDF, 1);
508+ }
509+ sci->Xsr &= (val | ssr_mask);
510+ sci_irq(sci, ERI);
511+ sci_irq(sci, RXI);
512+ sci_irq(sci, TXI);
513+ }
514+ break;
515+ case A_RDR:
516+ qemu_log_mask(LOG_GUEST_ERROR, "reneas_sci: RDR is read only.\n");
517+ break;
518+ case A_FCR: /* A_SCMR / A_SPTR */
519+ if (IS_SCI(sci)) {
520+ if (sci->feature == SCI_FEAT_SCI) {
521+ sci->sptr = val;
522+ } else {
523+ sci->scmr = val;
524+ }
525+ } else {
526+ sci->fcr = val;
527+ if (FIELD_EX16(sci->fcr, FCR, RFRST)) {
528+ fifo8_reset(&sci->rxfifo);
529+ update_event_time(sci, RXTOUT, 0);
530+ update_event_time(sci, RXNEXT, 0);
531+ }
532+ if (FIELD_EX16(sci->fcr, FCR, TFRST)) {
533+ sci->tdcnt = 0;
534+ }
535+ }
536+ break;
537+ case A_FDR: /* A_SEMR */
538+ if (IS_SCI(sci)) {
539+ SCI_IS_NOT_SUPPORTED(sci, SEMR);
540+ sci->semr = val;
541+ } else {
542+ qemu_log_mask(LOG_GUEST_ERROR, "reneas_sci: FDR is read only.\n");
543+ }
544+ break;
545+ case A_SPTR:
546+ if (IS_SCI(sci)) {
547+ goto error;
548+ } else {
549+ sci->sptr = val;
550+ }
551+ break;
552+ case A_LSR:
553+ if (IS_SCI(sci)) {
554+ goto error;
555+ } else {
556+ if (FIELD_EX16(sci->read_lsr, LSR, ORER) != 1) {
557+ val = FIELD_DP16(val, LSR, ORER, 1);
558+ }
559+ sci->lsr &= val;
560+ sci_irq(sci, ERI);
561+ }
562+ break;
563+ default:
564+ error:
565+ qemu_log_mask(LOG_UNIMP, "renesas_sci: Register 0x%" HWADDR_PRIX
566+ " not implemented\n", addr);
567+ }
568+}
569+
570+static uint64_t sci_read(void *opaque, hwaddr addr, unsigned size)
571+{
572+ RSCIState *sci = RSCI(opaque);
573+ uint64_t ret;
574+
575+ switch (sci->regsize) {
576+ case 8:
577+ addr <<= 1; break;
578+ case 32:
579+ addr >>= 1; break;
580+ }
581+
582+ switch (addr) {
583+ case A_SMR:
584+ return sci->smr;
585+ case A_BRR:
586+ return sci->brr;
587+ case A_SCR:
588+ return sci->scr;
589+ case A_TDR:
590+ if (IS_SCI(sci)) {
591+ return sci->tdr;
592+ } else {
593+ qemu_log_mask(LOG_GUEST_ERROR, "reneas_sci: TDR is write only.\n");
594+ return UINT64_MAX;
595+ }
596+ case A_FSR: /* A_SSR */
597+ sci->read_Xsr = sci->Xsr;
598+ return sci->Xsr;
599+ case A_RDR:
600+ ret = fifo8_pop(&sci->rxfifo);
601+ if (IS_SCIA(sci)) {
602+ sci->Xsr = FIELD_DP16(sci->Xsr, SSR, RDRF, 0);
603+ }
604+ return ret;
605+ case A_FCR: /* A_SCMR / A_SPTR */
606+ if (IS_SCI(sci)) {
607+ if (IS_SCIA(sci)) {
608+ return sci->scmr;
609+ } else {
610+ return sci->sptr;
611+ }
612+ } else {
613+ return sci->fcr & 0x7ff;
614+ }
615+ case A_FDR: /* A_SEMR */
616+ if (IS_SCI(sci)) {
617+ SCI_IS_NOT_SUPPORTED(sci, SEMR);
618+ return sci->semr;
619+ } else {
620+ ret = 0;
621+ ret = FIELD_DP16(ret, FDR, Rn, fifo8_num_used(&sci->rxfifo));
622+ ret = FIELD_DP16(ret, FDR, Tn, sci->tdcnt - transmit_byte(sci));
623+ return ret;
624+ }
625+ case A_SPTR:
626+ if (IS_SCI(sci)) {
627+ goto error;
628+ } else {
629+ return sci->sptr;
630+ }
631+ case A_LSR:
632+ if (IS_SCI(sci)) {
633+ goto error;
634+ } else {
635+ sci->read_lsr = sci->lsr;
636+ return sci->lsr;
637+ }
638+ default:
639+ error:
640+ qemu_log_mask(LOG_UNIMP, "renesas_sci: Register 0x%" HWADDR_PRIX
641+ " not implemented.\n", addr);
642+ }
643+ return UINT64_MAX;
644+}
645+
646+static const MemoryRegionOps sci_ops = {
647+ .write = sci_write,
648+ .read = sci_read,
649+ .endianness = DEVICE_NATIVE_ENDIAN,
650+ .impl = {
651+ .max_access_size = 4,
652+ },
653+};
654+
655+static void sci_register_init(RSCIState *sci)
656+{
657+ int i;
658+ sci->smr = sci->scr = 0x00;
659+ sci->brr = 0xff;
660+ if (IS_SCI(sci)) {
661+ sci->tdr = 0xff;
662+ sci->Xsr = 0x84;
663+ sci->scmr = 0x00;
664+ sci->semr = 0x00;
665+ sci->sptr = 0x00;
666+ } else {
667+ sci->Xsr = 0x0060;
668+ sci->fcr = 0x0000;
669+ sci->sptr = 0x0000;
670+ sci->lsr = 0x0000;
671+ }
672+ update_trtime(sci);
673+ for (i = 0; i < NR_SCI_EVENT; i++) {
674+ sci->event[i].time = 0;
675+ }
676+}
677+
678+static void sci_event(void *opaque, QEMUChrEvent event)
679+{
680+ RSCIState *sci = RSCI(opaque);
681+ if (event == CHR_EVENT_BREAK) {
682+ if (IS_SCI(sci)) {
683+ sci->Xsr = FIELD_DP16(sci->Xsr, SSR, FER, 1);
684+ } else {
685+ sci->Xsr = FIELD_DP16(sci->Xsr, FSR, BRK, 1);
686+ }
687+ sci_irq(sci, ERI);
688+ }
689+}
690+
691+static void rsci_realize(DeviceState *dev, Error **errp)
692+{
693+ SysBusDevice *d = SYS_BUS_DEVICE(dev);
694+ RSCIState *sci = RSCI(dev);
695+ int i;
696+ int size;
697+
698+ if (sci->input_freq == 0) {
699+ qemu_log_mask(LOG_GUEST_ERROR,
700+ "renesas_sci: input-freq property must be set.");
701+ return;
702+ }
703+ if (sci->regsize != 8 && sci->regsize != 16 && sci->regsize != 32) {
704+ qemu_log_mask(LOG_GUEST_ERROR,
705+ "renesas_sci: Invalid regsize.");
706+ return;
707+ }
708+
709+ size = IS_SCI(sci) ? 16 : 20;
710+ switch (sci->regsize) {
711+ case 8:
712+ size >>= 1;
713+ break;
714+ case 32:
715+ size <<= 1;
716+ break;
717+ }
718+ memory_region_init_io(&sci->memory, OBJECT(sci), &sci_ops,
719+ sci, "renesas-sci", size);
720+ sysbus_init_mmio(d, &sci->memory);
721+ memory_region_init_alias(&sci->memory_p4, NULL, "renesas-sci-p4",
722+ &sci->memory, 0, size);
723+ sysbus_init_mmio(d, &sci->memory_p4);
724+ memory_region_init_alias(&sci->memory_a7, NULL, "renesas-sci-a7",
725+ &sci->memory, 0, size);
726+ sysbus_init_mmio(d, &sci->memory_a7);
727+
728+ for (i = 0; i < SCI_NR_IRQ; i++) {
729+ sysbus_init_irq(d, &sci->irq[i]);
730+ }
731+ sci->event_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, sci_timer_event, sci);
732+
733+ qemu_chr_fe_set_handlers(&sci->chr, can_receive, sci_receive,
734+ sci_event, NULL, sci, NULL, true);
735+ fifo8_create(&sci->rxfifo, SCIF_FIFO_DEPTH);
736+ sci_register_init(sci);
737+}
738+
739+static const VMStateDescription vmstate_rsci = {
740+ .name = "renesas-sci",
741+ .version_id = 1,
742+ .minimum_version_id = 1,
743+ .fields = (VMStateField[]) {
744+ VMSTATE_END_OF_LIST()
745+ }
746+};
747+
748+static Property rsci_properties[] = {
749+ DEFINE_PROP_UINT64("input-freq", RSCIState, input_freq, 0),
750+ DEFINE_PROP_INT32("register-size", RSCIState, regsize, 8),
751+ DEFINE_PROP_INT32("feature", RSCIState, feature, 0),
752+ DEFINE_PROP_CHR("chardev", RSCIState, chr),
753+ DEFINE_PROP_END_OF_LIST(),
754+};
755+
756+static void rsci_init(Object *obj)
757+{
758+ RSCIState *sci = RSCI(obj);
759+ sci->event[RXTOUT].handler = sci_rx_timeout;
760+ sci->event[RXNEXT].handler = sci_rx_next;
761+ sci->event[TXEMPTY].handler = sci_tx_empty;
762+ sci->event[TXEND].handler = sci_tx_end;
763+}
764+static void rsci_class_init(ObjectClass *klass, void *data)
765+{
766+ DeviceClass *dc = DEVICE_CLASS(klass);
767+
768+ dc->realize = rsci_realize;
769+ dc->vmsd = &vmstate_rsci;
770+ device_class_set_props(dc, rsci_properties);
771+}
772+
773+static const TypeInfo rsci_info = {
774+ .name = TYPE_RENESAS_SCI,
775+ .parent = TYPE_SYS_BUS_DEVICE,
776+ .instance_size = sizeof(RSCIState),
777+ .instance_init = rsci_init,
778+ .class_init = rsci_class_init,
779+};
780+
781+static void rsci_register_types(void)
782+{
783+ type_register_static(&rsci_info);
784+}
785+
786+type_init(rsci_register_types)
--- /dev/null
+++ b/include/hw/char/renesas_sci.h
@@ -0,0 +1,77 @@
1+/*
2+ * Renesas Serial Communication Interface
3+ *
4+ * Copyright (c) 2020 Yoshinori Sato
5+ *
6+ * This code is licensed under the GPL version 2 or later.
7+ *
8+ */
9+
10+#include "chardev/char-fe.h"
11+#include "qemu/timer.h"
12+#include "qemu/fifo8.h"
13+#include "hw/sysbus.h"
14+
15+#define TYPE_RENESAS_SCI "renesas-sci"
16+#define RSCI(obj) OBJECT_CHECK(RSCIState, (obj), TYPE_RENESAS_SCI)
17+
18+enum {
19+ ERI = 0,
20+ RXI = 1,
21+ TXI = 2,
22+ TEI = 3,
23+ BRI = 3,
24+ SCI_NR_IRQ = 4,
25+};
26+
27+enum {
28+ SCI_FEAT_SCI = 0x00,
29+ SCI_FEAT_SCIA = 0x01,
30+ SCI_FEAT_SCIF = 0x10,
31+};
32+
33+enum {
34+ RXTOUT,
35+ RXNEXT,
36+ TXEMPTY,
37+ TXEND,
38+ NR_SCI_EVENT,
39+};
40+
41+typedef struct RSCIState {
42+ SysBusDevice parent_obj;
43+ MemoryRegion memory;
44+ MemoryRegion memory_p4;
45+ MemoryRegion memory_a7;
46+
47+ /* SCI register */
48+ uint8_t smr;
49+ uint8_t brr;
50+ uint8_t scr;
51+ uint8_t tdr;
52+ uint16_t Xsr;
53+ uint8_t scmr;
54+ uint8_t semr;
55+ uint16_t fcr;
56+ uint16_t sptr;
57+ uint16_t lsr;
58+
59+ /* internal use */
60+ uint16_t read_Xsr;
61+ uint16_t read_lsr;
62+ int64_t etu;
63+ int64_t trtime;
64+ int64_t tx_start_time;
65+ int tdcnt;
66+ int regsize;
67+ struct {
68+ int64_t time;
69+ int64_t (*handler)(struct RSCIState *sci);
70+ } event[NR_SCI_EVENT];
71+ QEMUTimer *event_timer;
72+ CharBackend chr;
73+ uint64_t input_freq;
74+ int feature;
75+ qemu_irq irq[SCI_NR_IRQ];
76+ Fifo8 rxfifo;
77+} RSCIState;