xref: /qemu/hw/char/sh_serial.c (revision 2f6df13748a7de19ab150a52af846f70303746e5)
12f062c72Sths /*
22f062c72Sths  * QEMU SCI/SCIF serial port emulation
32f062c72Sths  *
42f062c72Sths  * Copyright (c) 2007 Magnus Damm
52f062c72Sths  *
62f062c72Sths  * Based on serial.c - QEMU 16450 UART emulation
72f062c72Sths  * Copyright (c) 2003-2004 Fabrice Bellard
82f062c72Sths  *
92f062c72Sths  * Permission is hereby granted, free of charge, to any person obtaining a copy
102f062c72Sths  * of this software and associated documentation files (the "Software"), to deal
112f062c72Sths  * in the Software without restriction, including without limitation the rights
122f062c72Sths  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
132f062c72Sths  * copies of the Software, and to permit persons to whom the Software is
142f062c72Sths  * furnished to do so, subject to the following conditions:
152f062c72Sths  *
162f062c72Sths  * The above copyright notice and this permission notice shall be included in
172f062c72Sths  * all copies or substantial portions of the Software.
182f062c72Sths  *
192f062c72Sths  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
202f062c72Sths  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
212f062c72Sths  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
222f062c72Sths  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
232f062c72Sths  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
242f062c72Sths  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
252f062c72Sths  * THE SOFTWARE.
262f062c72Sths  */
2764552b6bSMarkus Armbruster 
280430891cSPeter Maydell #include "qemu/osdep.h"
2964552b6bSMarkus Armbruster #include "hw/irq.h"
300d09e41aSPaolo Bonzini #include "hw/sh4/sh.h"
314d43a603SMarc-André Lureau #include "chardev/char-fe.h"
3232a6ebecSMarc-André Lureau #include "qapi/error.h"
3371bb4ce1SGeert Uytterhoeven #include "qemu/timer.h"
343cf7ce43SBALATON Zoltan #include "qemu/log.h"
35ad52cfc1SBALATON Zoltan #include "trace.h"
362f062c72Sths 
372f062c72Sths #define SH_SERIAL_FLAG_TEND (1 << 0)
382f062c72Sths #define SH_SERIAL_FLAG_TDE  (1 << 1)
392f062c72Sths #define SH_SERIAL_FLAG_RDF  (1 << 2)
402f062c72Sths #define SH_SERIAL_FLAG_BRK  (1 << 3)
412f062c72Sths #define SH_SERIAL_FLAG_DR   (1 << 4)
422f062c72Sths 
4363242a00Saurel32 #define SH_RX_FIFO_LENGTH (16)
4463242a00Saurel32 
452f062c72Sths typedef struct {
469a9d0b81SBenoît Canet     MemoryRegion iomem;
479a9d0b81SBenoît Canet     MemoryRegion iomem_p4;
489a9d0b81SBenoît Canet     MemoryRegion iomem_a7;
492f062c72Sths     uint8_t smr;
502f062c72Sths     uint8_t brr;
512f062c72Sths     uint8_t scr;
522f062c72Sths     uint8_t dr; /* ftdr / tdr */
532f062c72Sths     uint8_t sr; /* fsr / ssr */
542f062c72Sths     uint16_t fcr;
552f062c72Sths     uint8_t sptr;
562f062c72Sths 
5763242a00Saurel32     uint8_t rx_fifo[SH_RX_FIFO_LENGTH]; /* frdr / rdr */
582f062c72Sths     uint8_t rx_cnt;
5963242a00Saurel32     uint8_t rx_tail;
6063242a00Saurel32     uint8_t rx_head;
612f062c72Sths 
622f062c72Sths     int freq;
632f062c72Sths     int feat;
642f062c72Sths     int flags;
6563242a00Saurel32     int rtrg;
662f062c72Sths 
6732a6ebecSMarc-André Lureau     CharBackend chr;
6871bb4ce1SGeert Uytterhoeven     QEMUTimer *fifo_timeout_timer;
6971bb4ce1SGeert Uytterhoeven     uint64_t etu; /* Elementary Time Unit (ns) */
70bf5b7423Saurel32 
714e7ed2d1Saurel32     qemu_irq eri;
724e7ed2d1Saurel32     qemu_irq rxi;
734e7ed2d1Saurel32     qemu_irq txi;
744e7ed2d1Saurel32     qemu_irq tei;
754e7ed2d1Saurel32     qemu_irq bri;
76*2f6df137SBALATON Zoltan } SHSerialState;
772f062c72Sths 
78*2f6df137SBALATON Zoltan static void sh_serial_clear_fifo(SHSerialState *s)
7963242a00Saurel32 {
8063242a00Saurel32     memset(s->rx_fifo, 0, SH_RX_FIFO_LENGTH);
8163242a00Saurel32     s->rx_cnt = 0;
8263242a00Saurel32     s->rx_head = 0;
8363242a00Saurel32     s->rx_tail = 0;
8463242a00Saurel32 }
8563242a00Saurel32 
86a8170e5eSAvi Kivity static void sh_serial_write(void *opaque, hwaddr offs,
879a9d0b81SBenoît Canet                             uint64_t val, unsigned size)
882f062c72Sths {
89*2f6df137SBALATON Zoltan     SHSerialState *s = opaque;
902f062c72Sths     unsigned char ch;
912f062c72Sths 
92ad52cfc1SBALATON Zoltan     trace_sh_serial_write(size, offs, val);
932f062c72Sths     switch (offs) {
942f062c72Sths     case 0x00: /* SMR */
952f062c72Sths         s->smr = val & ((s->feat & SH_SERIAL_FEAT_SCIF) ? 0x7b : 0xff);
962f062c72Sths         return;
972f062c72Sths     case 0x04: /* BRR */
982f062c72Sths         s->brr = val;
992f062c72Sths         return;
1002f062c72Sths     case 0x08: /* SCR */
10163242a00Saurel32         /* TODO : For SH7751, SCIF mask should be 0xfb. */
102bf5b7423Saurel32         s->scr = val & ((s->feat & SH_SERIAL_FEAT_SCIF) ? 0xfa : 0xff);
103ac3c9e74SBALATON Zoltan         if (!(val & (1 << 5))) {
1042f062c72Sths             s->flags |= SH_SERIAL_FLAG_TEND;
105ac3c9e74SBALATON Zoltan         }
106bf5b7423Saurel32         if ((s->feat & SH_SERIAL_FEAT_SCIF) && s->txi) {
1074e7ed2d1Saurel32             qemu_set_irq(s->txi, val & (1 << 7));
108bf5b7423Saurel32         }
1094e7ed2d1Saurel32         if (!(val & (1 << 6))) {
1104e7ed2d1Saurel32             qemu_set_irq(s->rxi, 0);
11163242a00Saurel32         }
1122f062c72Sths         return;
1132f062c72Sths     case 0x0c: /* FTDR / TDR */
11430650701SAnton Nefedov         if (qemu_chr_fe_backend_connected(&s->chr)) {
1152f062c72Sths             ch = val;
11622138965SBALATON Zoltan             /*
11722138965SBALATON Zoltan              * XXX this blocks entire thread. Rewrite to use
11822138965SBALATON Zoltan              * qemu_chr_fe_write and background I/O callbacks
11922138965SBALATON Zoltan              */
1205345fdb4SMarc-André Lureau             qemu_chr_fe_write_all(&s->chr, &ch, 1);
1212f062c72Sths         }
1222f062c72Sths         s->dr = val;
1232f062c72Sths         s->flags &= ~SH_SERIAL_FLAG_TDE;
1242f062c72Sths         return;
1252f062c72Sths #if 0
1262f062c72Sths     case 0x14: /* FRDR / RDR */
1272f062c72Sths         ret = 0;
1282f062c72Sths         break;
1292f062c72Sths #endif
1302f062c72Sths     }
1312f062c72Sths     if (s->feat & SH_SERIAL_FEAT_SCIF) {
1322f062c72Sths         switch (offs) {
1332f062c72Sths         case 0x10: /* FSR */
134ac3c9e74SBALATON Zoltan             if (!(val & (1 << 6))) {
1352f062c72Sths                 s->flags &= ~SH_SERIAL_FLAG_TEND;
136ac3c9e74SBALATON Zoltan             }
137ac3c9e74SBALATON Zoltan             if (!(val & (1 << 5))) {
1382f062c72Sths                 s->flags &= ~SH_SERIAL_FLAG_TDE;
139ac3c9e74SBALATON Zoltan             }
140ac3c9e74SBALATON Zoltan             if (!(val & (1 << 4))) {
1412f062c72Sths                 s->flags &= ~SH_SERIAL_FLAG_BRK;
142ac3c9e74SBALATON Zoltan             }
143ac3c9e74SBALATON Zoltan             if (!(val & (1 << 1))) {
1442f062c72Sths                 s->flags &= ~SH_SERIAL_FLAG_RDF;
145ac3c9e74SBALATON Zoltan             }
146ac3c9e74SBALATON Zoltan             if (!(val & (1 << 0))) {
1472f062c72Sths                 s->flags &= ~SH_SERIAL_FLAG_DR;
148ac3c9e74SBALATON Zoltan             }
14963242a00Saurel32 
15063242a00Saurel32             if (!(val & (1 << 1)) || !(val & (1 << 0))) {
1514e7ed2d1Saurel32                 if (s->rxi) {
1524e7ed2d1Saurel32                     qemu_set_irq(s->rxi, 0);
15363242a00Saurel32                 }
15463242a00Saurel32             }
1552f062c72Sths             return;
1562f062c72Sths         case 0x18: /* FCR */
1572f062c72Sths             s->fcr = val;
15863242a00Saurel32             switch ((val >> 6) & 3) {
15963242a00Saurel32             case 0:
16063242a00Saurel32                 s->rtrg = 1;
16163242a00Saurel32                 break;
16263242a00Saurel32             case 1:
16363242a00Saurel32                 s->rtrg = 4;
16463242a00Saurel32                 break;
16563242a00Saurel32             case 2:
16663242a00Saurel32                 s->rtrg = 8;
16763242a00Saurel32                 break;
16863242a00Saurel32             case 3:
16963242a00Saurel32                 s->rtrg = 14;
17063242a00Saurel32                 break;
17163242a00Saurel32             }
17263242a00Saurel32             if (val & (1 << 1)) {
17363242a00Saurel32                 sh_serial_clear_fifo(s);
17463242a00Saurel32                 s->sr &= ~(1 << 1);
17563242a00Saurel32             }
17663242a00Saurel32 
1772f062c72Sths             return;
1782f062c72Sths         case 0x20: /* SPTR */
17963242a00Saurel32             s->sptr = val & 0xf3;
1802f062c72Sths             return;
1812f062c72Sths         case 0x24: /* LSR */
1822f062c72Sths             return;
1832f062c72Sths         }
184f94bff13SBALATON Zoltan     } else {
1852f062c72Sths         switch (offs) {
186d1f193b0Saurel32 #if 0
1872f062c72Sths         case 0x0c:
1882f062c72Sths             ret = s->dr;
1892f062c72Sths             break;
1902f062c72Sths         case 0x10:
1912f062c72Sths             ret = 0;
1922f062c72Sths             break;
1932f062c72Sths #endif
194d1f193b0Saurel32         case 0x1c:
195d1f193b0Saurel32             s->sptr = val & 0x8f;
196d1f193b0Saurel32             return;
197d1f193b0Saurel32         }
1982f062c72Sths     }
1993cf7ce43SBALATON Zoltan     qemu_log_mask(LOG_GUEST_ERROR,
2003cf7ce43SBALATON Zoltan                   "%s: unsupported write to 0x%02" HWADDR_PRIx "\n",
2013cf7ce43SBALATON Zoltan                   __func__, offs);
2022f062c72Sths }
2032f062c72Sths 
204a8170e5eSAvi Kivity static uint64_t sh_serial_read(void *opaque, hwaddr offs,
2059a9d0b81SBenoît Canet                                unsigned size)
2062f062c72Sths {
207*2f6df137SBALATON Zoltan     SHSerialState *s = opaque;
2083cf7ce43SBALATON Zoltan     uint32_t ret = UINT32_MAX;
2092f062c72Sths 
2102f062c72Sths #if 0
2112f062c72Sths     switch (offs) {
2122f062c72Sths     case 0x00:
2132f062c72Sths         ret = s->smr;
2142f062c72Sths         break;
2152f062c72Sths     case 0x04:
2162f062c72Sths         ret = s->brr;
2172f062c72Sths         break;
2182f062c72Sths     case 0x08:
2192f062c72Sths         ret = s->scr;
2202f062c72Sths         break;
2212f062c72Sths     case 0x14:
2222f062c72Sths         ret = 0;
2232f062c72Sths         break;
2242f062c72Sths     }
2252f062c72Sths #endif
2262f062c72Sths     if (s->feat & SH_SERIAL_FEAT_SCIF) {
2272f062c72Sths         switch (offs) {
228bf5b7423Saurel32         case 0x00: /* SMR */
229bf5b7423Saurel32             ret = s->smr;
230bf5b7423Saurel32             break;
231bf5b7423Saurel32         case 0x08: /* SCR */
232bf5b7423Saurel32             ret = s->scr;
233bf5b7423Saurel32             break;
2342f062c72Sths         case 0x10: /* FSR */
2352f062c72Sths             ret = 0;
236ac3c9e74SBALATON Zoltan             if (s->flags & SH_SERIAL_FLAG_TEND) {
2372f062c72Sths                 ret |= (1 << 6);
238ac3c9e74SBALATON Zoltan             }
239ac3c9e74SBALATON Zoltan             if (s->flags & SH_SERIAL_FLAG_TDE) {
2402f062c72Sths                 ret |= (1 << 5);
241ac3c9e74SBALATON Zoltan             }
242ac3c9e74SBALATON Zoltan             if (s->flags & SH_SERIAL_FLAG_BRK) {
2432f062c72Sths                 ret |= (1 << 4);
244ac3c9e74SBALATON Zoltan             }
245ac3c9e74SBALATON Zoltan             if (s->flags & SH_SERIAL_FLAG_RDF) {
2462f062c72Sths                 ret |= (1 << 1);
247ac3c9e74SBALATON Zoltan             }
248ac3c9e74SBALATON Zoltan             if (s->flags & SH_SERIAL_FLAG_DR) {
2492f062c72Sths                 ret |= (1 << 0);
250ac3c9e74SBALATON Zoltan             }
2512f062c72Sths 
252ac3c9e74SBALATON Zoltan             if (s->scr & (1 << 5)) {
2532f062c72Sths                 s->flags |= SH_SERIAL_FLAG_TDE | SH_SERIAL_FLAG_TEND;
254ac3c9e74SBALATON Zoltan             }
2552f062c72Sths 
2562f062c72Sths             break;
25763242a00Saurel32         case 0x14:
25863242a00Saurel32             if (s->rx_cnt > 0) {
25963242a00Saurel32                 ret = s->rx_fifo[s->rx_tail++];
26063242a00Saurel32                 s->rx_cnt--;
261ac3c9e74SBALATON Zoltan                 if (s->rx_tail == SH_RX_FIFO_LENGTH) {
26263242a00Saurel32                     s->rx_tail = 0;
263ac3c9e74SBALATON Zoltan                 }
264ac3c9e74SBALATON Zoltan                 if (s->rx_cnt < s->rtrg) {
26563242a00Saurel32                     s->flags &= ~SH_SERIAL_FLAG_RDF;
26663242a00Saurel32                 }
267ac3c9e74SBALATON Zoltan             }
26863242a00Saurel32             break;
2692f062c72Sths         case 0x18:
2702f062c72Sths             ret = s->fcr;
2712f062c72Sths             break;
2722f062c72Sths         case 0x1c:
2732f062c72Sths             ret = s->rx_cnt;
2742f062c72Sths             break;
2752f062c72Sths         case 0x20:
2762f062c72Sths             ret = s->sptr;
2772f062c72Sths             break;
2782f062c72Sths         case 0x24:
2792f062c72Sths             ret = 0;
2802f062c72Sths             break;
2812f062c72Sths         }
282f94bff13SBALATON Zoltan     } else {
2832f062c72Sths         switch (offs) {
284d1f193b0Saurel32 #if 0
2852f062c72Sths         case 0x0c:
2862f062c72Sths             ret = s->dr;
2872f062c72Sths             break;
2882f062c72Sths         case 0x10:
2892f062c72Sths             ret = 0;
2902f062c72Sths             break;
29163242a00Saurel32         case 0x14:
29263242a00Saurel32             ret = s->rx_fifo[0];
29363242a00Saurel32             break;
294d1f193b0Saurel32 #endif
2952f062c72Sths         case 0x1c:
2962f062c72Sths             ret = s->sptr;
2972f062c72Sths             break;
2982f062c72Sths         }
2992f062c72Sths     }
300ad52cfc1SBALATON Zoltan     trace_sh_serial_read(size, offs, ret);
3012f062c72Sths 
3023cf7ce43SBALATON Zoltan     if (ret > UINT16_MAX) {
3033cf7ce43SBALATON Zoltan         qemu_log_mask(LOG_GUEST_ERROR,
3043cf7ce43SBALATON Zoltan                       "%s: unsupported read from 0x%02" HWADDR_PRIx "\n",
3053cf7ce43SBALATON Zoltan                       __func__, offs);
3063cf7ce43SBALATON Zoltan         ret = 0;
3072f062c72Sths     }
3082f062c72Sths 
3092f062c72Sths     return ret;
3102f062c72Sths }
3112f062c72Sths 
312*2f6df137SBALATON Zoltan static int sh_serial_can_receive(SHSerialState *s)
3132f062c72Sths {
31463242a00Saurel32     return s->scr & (1 << 4);
3152f062c72Sths }
3162f062c72Sths 
317*2f6df137SBALATON Zoltan static void sh_serial_receive_break(SHSerialState *s)
3182f062c72Sths {
319ac3c9e74SBALATON Zoltan     if (s->feat & SH_SERIAL_FEAT_SCIF) {
32063242a00Saurel32         s->sr |= (1 << 4);
3212f062c72Sths     }
322ac3c9e74SBALATON Zoltan }
3232f062c72Sths 
3242f062c72Sths static int sh_serial_can_receive1(void *opaque)
3252f062c72Sths {
326*2f6df137SBALATON Zoltan     SHSerialState *s = opaque;
3272f062c72Sths     return sh_serial_can_receive(s);
3282f062c72Sths }
3292f062c72Sths 
33071bb4ce1SGeert Uytterhoeven static void sh_serial_timeout_int(void *opaque)
33171bb4ce1SGeert Uytterhoeven {
332*2f6df137SBALATON Zoltan     SHSerialState *s = opaque;
33371bb4ce1SGeert Uytterhoeven 
33471bb4ce1SGeert Uytterhoeven     s->flags |= SH_SERIAL_FLAG_RDF;
33571bb4ce1SGeert Uytterhoeven     if (s->scr & (1 << 6) && s->rxi) {
33671bb4ce1SGeert Uytterhoeven         qemu_set_irq(s->rxi, 1);
33771bb4ce1SGeert Uytterhoeven     }
33871bb4ce1SGeert Uytterhoeven }
33971bb4ce1SGeert Uytterhoeven 
3402f062c72Sths static void sh_serial_receive1(void *opaque, const uint8_t *buf, int size)
3412f062c72Sths {
342*2f6df137SBALATON Zoltan     SHSerialState *s = opaque;
343b7d2b020SAurelien Jarno 
344b7d2b020SAurelien Jarno     if (s->feat & SH_SERIAL_FEAT_SCIF) {
345b7d2b020SAurelien Jarno         int i;
346b7d2b020SAurelien Jarno         for (i = 0; i < size; i++) {
347b7d2b020SAurelien Jarno             if (s->rx_cnt < SH_RX_FIFO_LENGTH) {
348b7d2b020SAurelien Jarno                 s->rx_fifo[s->rx_head++] = buf[i];
349b7d2b020SAurelien Jarno                 if (s->rx_head == SH_RX_FIFO_LENGTH) {
350b7d2b020SAurelien Jarno                     s->rx_head = 0;
351b7d2b020SAurelien Jarno                 }
352b7d2b020SAurelien Jarno                 s->rx_cnt++;
353b7d2b020SAurelien Jarno                 if (s->rx_cnt >= s->rtrg) {
354b7d2b020SAurelien Jarno                     s->flags |= SH_SERIAL_FLAG_RDF;
355b7d2b020SAurelien Jarno                     if (s->scr & (1 << 6) && s->rxi) {
35671bb4ce1SGeert Uytterhoeven                         timer_del(s->fifo_timeout_timer);
357b7d2b020SAurelien Jarno                         qemu_set_irq(s->rxi, 1);
358b7d2b020SAurelien Jarno                     }
35971bb4ce1SGeert Uytterhoeven                 } else {
36071bb4ce1SGeert Uytterhoeven                     timer_mod(s->fifo_timeout_timer,
36171bb4ce1SGeert Uytterhoeven                         qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + 15 * s->etu);
362b7d2b020SAurelien Jarno                 }
363b7d2b020SAurelien Jarno             }
364b7d2b020SAurelien Jarno         }
365b7d2b020SAurelien Jarno     } else {
366b7d2b020SAurelien Jarno         s->rx_fifo[0] = buf[0];
367b7d2b020SAurelien Jarno     }
3682f062c72Sths }
3692f062c72Sths 
370083b266fSPhilippe Mathieu-Daudé static void sh_serial_event(void *opaque, QEMUChrEvent event)
3712f062c72Sths {
372*2f6df137SBALATON Zoltan     SHSerialState *s = opaque;
373ac3c9e74SBALATON Zoltan     if (event == CHR_EVENT_BREAK) {
3742f062c72Sths         sh_serial_receive_break(s);
3752f062c72Sths     }
376ac3c9e74SBALATON Zoltan }
3772f062c72Sths 
3789a9d0b81SBenoît Canet static const MemoryRegionOps sh_serial_ops = {
3799a9d0b81SBenoît Canet     .read = sh_serial_read,
3809a9d0b81SBenoît Canet     .write = sh_serial_write,
3819a9d0b81SBenoît Canet     .endianness = DEVICE_NATIVE_ENDIAN,
3822f062c72Sths };
3832f062c72Sths 
3849a9d0b81SBenoît Canet void sh_serial_init(MemoryRegion *sysmem,
385a8170e5eSAvi Kivity                     hwaddr base, int feat,
3860ec7b3e7SMarc-André Lureau                     uint32_t freq, Chardev *chr,
3874e7ed2d1Saurel32                     qemu_irq eri_source,
3884e7ed2d1Saurel32                     qemu_irq rxi_source,
3894e7ed2d1Saurel32                     qemu_irq txi_source,
3904e7ed2d1Saurel32                     qemu_irq tei_source,
3914e7ed2d1Saurel32                     qemu_irq bri_source)
3922f062c72Sths {
393*2f6df137SBALATON Zoltan     SHSerialState *s = g_malloc0(sizeof(*s));
3942f062c72Sths 
3952f062c72Sths     s->feat = feat;
3962f062c72Sths     s->flags = SH_SERIAL_FLAG_TEND | SH_SERIAL_FLAG_TDE;
39763242a00Saurel32     s->rtrg = 1;
3982f062c72Sths 
3992f062c72Sths     s->smr = 0;
4002f062c72Sths     s->brr = 0xff;
401b7d35e65Sbalrog     s->scr = 1 << 5; /* pretend that TX is enabled so early printk works */
4022f062c72Sths     s->sptr = 0;
4032f062c72Sths 
4042f062c72Sths     if (feat & SH_SERIAL_FEAT_SCIF) {
4052f062c72Sths         s->fcr = 0;
406f94bff13SBALATON Zoltan     } else {
4072f062c72Sths         s->dr = 0xff;
4082f062c72Sths     }
4092f062c72Sths 
41063242a00Saurel32     sh_serial_clear_fifo(s);
4112f062c72Sths 
4122c9b15caSPaolo Bonzini     memory_region_init_io(&s->iomem, NULL, &sh_serial_ops, s,
4139a9d0b81SBenoît Canet                           "serial", 0x100000000ULL);
4149a9d0b81SBenoît Canet 
4152c9b15caSPaolo Bonzini     memory_region_init_alias(&s->iomem_p4, NULL, "serial-p4", &s->iomem,
4169a9d0b81SBenoît Canet                              0, 0x28);
4179a9d0b81SBenoît Canet     memory_region_add_subregion(sysmem, P4ADDR(base), &s->iomem_p4);
4189a9d0b81SBenoît Canet 
4192c9b15caSPaolo Bonzini     memory_region_init_alias(&s->iomem_a7, NULL, "serial-a7", &s->iomem,
4209a9d0b81SBenoît Canet                              0, 0x28);
4219a9d0b81SBenoît Canet     memory_region_add_subregion(sysmem, A7ADDR(base), &s->iomem_a7);
4222f062c72Sths 
423456d6069SHans de Goede     if (chr) {
42432a6ebecSMarc-André Lureau         qemu_chr_fe_init(&s->chr, chr, &error_abort);
4255345fdb4SMarc-André Lureau         qemu_chr_fe_set_handlers(&s->chr, sh_serial_can_receive1,
4265345fdb4SMarc-André Lureau                                  sh_serial_receive1,
42781517ba3SAnton Nefedov                                  sh_serial_event, NULL, s, NULL, true);
428456d6069SHans de Goede     }
429bf5b7423Saurel32 
43071bb4ce1SGeert Uytterhoeven     s->fifo_timeout_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL,
43171bb4ce1SGeert Uytterhoeven                                          sh_serial_timeout_int, s);
43271bb4ce1SGeert Uytterhoeven     s->etu = NANOSECONDS_PER_SECOND / 9600;
433bf5b7423Saurel32     s->eri = eri_source;
434bf5b7423Saurel32     s->rxi = rxi_source;
435bf5b7423Saurel32     s->txi = txi_source;
436bf5b7423Saurel32     s->tei = tei_source;
437bf5b7423Saurel32     s->bri = bri_source;
4382f062c72Sths }
439