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"
29beeb5209SBALATON Zoltan #include "hw/sysbus.h"
3064552b6bSMarkus Armbruster #include "hw/irq.h"
31beeb5209SBALATON Zoltan #include "hw/qdev-core.h"
32beeb5209SBALATON Zoltan #include "hw/qdev-properties.h"
33beeb5209SBALATON Zoltan #include "hw/qdev-properties-system.h"
340d09e41aSPaolo Bonzini #include "hw/sh4/sh.h"
354d43a603SMarc-André Lureau #include "chardev/char-fe.h"
3632a6ebecSMarc-André Lureau #include "qapi/error.h"
3771bb4ce1SGeert Uytterhoeven #include "qemu/timer.h"
383cf7ce43SBALATON Zoltan #include "qemu/log.h"
39ad52cfc1SBALATON Zoltan #include "trace.h"
402f062c72Sths
412f062c72Sths #define SH_SERIAL_FLAG_TEND (1 << 0)
422f062c72Sths #define SH_SERIAL_FLAG_TDE (1 << 1)
432f062c72Sths #define SH_SERIAL_FLAG_RDF (1 << 2)
442f062c72Sths #define SH_SERIAL_FLAG_BRK (1 << 3)
452f062c72Sths #define SH_SERIAL_FLAG_DR (1 << 4)
462f062c72Sths
4763242a00Saurel32 #define SH_RX_FIFO_LENGTH (16)
4863242a00Saurel32
49beeb5209SBALATON Zoltan OBJECT_DECLARE_SIMPLE_TYPE(SHSerialState, SH_SERIAL)
50beeb5209SBALATON Zoltan
51beeb5209SBALATON Zoltan struct SHSerialState {
52beeb5209SBALATON Zoltan SysBusDevice parent;
532f062c72Sths uint8_t smr;
542f062c72Sths uint8_t brr;
552f062c72Sths uint8_t scr;
562f062c72Sths uint8_t dr; /* ftdr / tdr */
572f062c72Sths uint8_t sr; /* fsr / ssr */
582f062c72Sths uint16_t fcr;
592f062c72Sths uint8_t sptr;
602f062c72Sths
6163242a00Saurel32 uint8_t rx_fifo[SH_RX_FIFO_LENGTH]; /* frdr / rdr */
622f062c72Sths uint8_t rx_cnt;
6363242a00Saurel32 uint8_t rx_tail;
6463242a00Saurel32 uint8_t rx_head;
652f062c72Sths
66beeb5209SBALATON Zoltan uint8_t feat;
672f062c72Sths int flags;
6863242a00Saurel32 int rtrg;
692f062c72Sths
7032a6ebecSMarc-André Lureau CharBackend chr;
715b344b02SBALATON Zoltan QEMUTimer fifo_timeout_timer;
7271bb4ce1SGeert Uytterhoeven uint64_t etu; /* Elementary Time Unit (ns) */
73bf5b7423Saurel32
744e7ed2d1Saurel32 qemu_irq eri;
754e7ed2d1Saurel32 qemu_irq rxi;
764e7ed2d1Saurel32 qemu_irq txi;
774e7ed2d1Saurel32 qemu_irq tei;
784e7ed2d1Saurel32 qemu_irq bri;
79beeb5209SBALATON Zoltan };
80beeb5209SBALATON Zoltan
81beeb5209SBALATON Zoltan typedef struct {} SHSerialStateClass;
82beeb5209SBALATON Zoltan
OBJECT_DEFINE_TYPE(SHSerialState,sh_serial,SH_SERIAL,SYS_BUS_DEVICE)83beeb5209SBALATON Zoltan OBJECT_DEFINE_TYPE(SHSerialState, sh_serial, SH_SERIAL, SYS_BUS_DEVICE)
842f062c72Sths
852f6df137SBALATON Zoltan static void sh_serial_clear_fifo(SHSerialState *s)
8663242a00Saurel32 {
8763242a00Saurel32 memset(s->rx_fifo, 0, SH_RX_FIFO_LENGTH);
8863242a00Saurel32 s->rx_cnt = 0;
8963242a00Saurel32 s->rx_head = 0;
9063242a00Saurel32 s->rx_tail = 0;
9163242a00Saurel32 }
9263242a00Saurel32
sh_serial_write(void * opaque,hwaddr offs,uint64_t val,unsigned size)93a8170e5eSAvi Kivity static void sh_serial_write(void *opaque, hwaddr offs,
949a9d0b81SBenoît Canet uint64_t val, unsigned size)
952f062c72Sths {
962f6df137SBALATON Zoltan SHSerialState *s = opaque;
9744ae04f0SBALATON Zoltan DeviceState *d = DEVICE(s);
982f062c72Sths unsigned char ch;
992f062c72Sths
10044ae04f0SBALATON Zoltan trace_sh_serial_write(d->id, size, offs, val);
1012f062c72Sths switch (offs) {
1022f062c72Sths case 0x00: /* SMR */
1032f062c72Sths s->smr = val & ((s->feat & SH_SERIAL_FEAT_SCIF) ? 0x7b : 0xff);
1042f062c72Sths return;
1052f062c72Sths case 0x04: /* BRR */
1062f062c72Sths s->brr = val;
1072f062c72Sths return;
1082f062c72Sths case 0x08: /* SCR */
10963242a00Saurel32 /* TODO : For SH7751, SCIF mask should be 0xfb. */
110bf5b7423Saurel32 s->scr = val & ((s->feat & SH_SERIAL_FEAT_SCIF) ? 0xfa : 0xff);
111ac3c9e74SBALATON Zoltan if (!(val & (1 << 5))) {
1122f062c72Sths s->flags |= SH_SERIAL_FLAG_TEND;
113ac3c9e74SBALATON Zoltan }
114bf5b7423Saurel32 if ((s->feat & SH_SERIAL_FEAT_SCIF) && s->txi) {
1154e7ed2d1Saurel32 qemu_set_irq(s->txi, val & (1 << 7));
116bf5b7423Saurel32 }
1174e7ed2d1Saurel32 if (!(val & (1 << 6))) {
1184e7ed2d1Saurel32 qemu_set_irq(s->rxi, 0);
11963242a00Saurel32 }
1202f062c72Sths return;
1212f062c72Sths case 0x0c: /* FTDR / TDR */
12230650701SAnton Nefedov if (qemu_chr_fe_backend_connected(&s->chr)) {
1232f062c72Sths ch = val;
12422138965SBALATON Zoltan /*
12522138965SBALATON Zoltan * XXX this blocks entire thread. Rewrite to use
12622138965SBALATON Zoltan * qemu_chr_fe_write and background I/O callbacks
12722138965SBALATON Zoltan */
1285345fdb4SMarc-André Lureau qemu_chr_fe_write_all(&s->chr, &ch, 1);
1292f062c72Sths }
1302f062c72Sths s->dr = val;
1312f062c72Sths s->flags &= ~SH_SERIAL_FLAG_TDE;
1322f062c72Sths return;
1332f062c72Sths #if 0
1342f062c72Sths case 0x14: /* FRDR / RDR */
1352f062c72Sths ret = 0;
1362f062c72Sths break;
1372f062c72Sths #endif
1382f062c72Sths }
1392f062c72Sths if (s->feat & SH_SERIAL_FEAT_SCIF) {
1402f062c72Sths switch (offs) {
1412f062c72Sths case 0x10: /* FSR */
142ac3c9e74SBALATON Zoltan if (!(val & (1 << 6))) {
1432f062c72Sths s->flags &= ~SH_SERIAL_FLAG_TEND;
144ac3c9e74SBALATON Zoltan }
145ac3c9e74SBALATON Zoltan if (!(val & (1 << 5))) {
1462f062c72Sths s->flags &= ~SH_SERIAL_FLAG_TDE;
147ac3c9e74SBALATON Zoltan }
148ac3c9e74SBALATON Zoltan if (!(val & (1 << 4))) {
1492f062c72Sths s->flags &= ~SH_SERIAL_FLAG_BRK;
150ac3c9e74SBALATON Zoltan }
151ac3c9e74SBALATON Zoltan if (!(val & (1 << 1))) {
1522f062c72Sths s->flags &= ~SH_SERIAL_FLAG_RDF;
153ac3c9e74SBALATON Zoltan }
154ac3c9e74SBALATON Zoltan if (!(val & (1 << 0))) {
1552f062c72Sths s->flags &= ~SH_SERIAL_FLAG_DR;
156ac3c9e74SBALATON Zoltan }
15763242a00Saurel32
15863242a00Saurel32 if (!(val & (1 << 1)) || !(val & (1 << 0))) {
1594e7ed2d1Saurel32 if (s->rxi) {
1604e7ed2d1Saurel32 qemu_set_irq(s->rxi, 0);
16163242a00Saurel32 }
16263242a00Saurel32 }
1632f062c72Sths return;
1642f062c72Sths case 0x18: /* FCR */
1652f062c72Sths s->fcr = val;
16663242a00Saurel32 switch ((val >> 6) & 3) {
16763242a00Saurel32 case 0:
16863242a00Saurel32 s->rtrg = 1;
16963242a00Saurel32 break;
17063242a00Saurel32 case 1:
17163242a00Saurel32 s->rtrg = 4;
17263242a00Saurel32 break;
17363242a00Saurel32 case 2:
17463242a00Saurel32 s->rtrg = 8;
17563242a00Saurel32 break;
17663242a00Saurel32 case 3:
17763242a00Saurel32 s->rtrg = 14;
17863242a00Saurel32 break;
17963242a00Saurel32 }
18063242a00Saurel32 if (val & (1 << 1)) {
18163242a00Saurel32 sh_serial_clear_fifo(s);
18263242a00Saurel32 s->sr &= ~(1 << 1);
18363242a00Saurel32 }
18463242a00Saurel32
1852f062c72Sths return;
1862f062c72Sths case 0x20: /* SPTR */
18763242a00Saurel32 s->sptr = val & 0xf3;
1882f062c72Sths return;
1892f062c72Sths case 0x24: /* LSR */
1902f062c72Sths return;
1912f062c72Sths }
192f94bff13SBALATON Zoltan } else {
1932f062c72Sths switch (offs) {
194d1f193b0Saurel32 #if 0
1952f062c72Sths case 0x0c:
1962f062c72Sths ret = s->dr;
1972f062c72Sths break;
1982f062c72Sths case 0x10:
1992f062c72Sths ret = 0;
2002f062c72Sths break;
2012f062c72Sths #endif
202d1f193b0Saurel32 case 0x1c:
203d1f193b0Saurel32 s->sptr = val & 0x8f;
204d1f193b0Saurel32 return;
205d1f193b0Saurel32 }
2062f062c72Sths }
2073cf7ce43SBALATON Zoltan qemu_log_mask(LOG_GUEST_ERROR,
2083cf7ce43SBALATON Zoltan "%s: unsupported write to 0x%02" HWADDR_PRIx "\n",
2093cf7ce43SBALATON Zoltan __func__, offs);
2102f062c72Sths }
2112f062c72Sths
sh_serial_read(void * opaque,hwaddr offs,unsigned size)212a8170e5eSAvi Kivity static uint64_t sh_serial_read(void *opaque, hwaddr offs,
2139a9d0b81SBenoît Canet unsigned size)
2142f062c72Sths {
2152f6df137SBALATON Zoltan SHSerialState *s = opaque;
21644ae04f0SBALATON Zoltan DeviceState *d = DEVICE(s);
2173cf7ce43SBALATON Zoltan uint32_t ret = UINT32_MAX;
2182f062c72Sths
2192f062c72Sths #if 0
2202f062c72Sths switch (offs) {
2212f062c72Sths case 0x00:
2222f062c72Sths ret = s->smr;
2232f062c72Sths break;
2242f062c72Sths case 0x04:
2252f062c72Sths ret = s->brr;
2262f062c72Sths break;
2272f062c72Sths case 0x08:
2282f062c72Sths ret = s->scr;
2292f062c72Sths break;
2302f062c72Sths case 0x14:
2312f062c72Sths ret = 0;
2322f062c72Sths break;
2332f062c72Sths }
2342f062c72Sths #endif
2352f062c72Sths if (s->feat & SH_SERIAL_FEAT_SCIF) {
2362f062c72Sths switch (offs) {
237bf5b7423Saurel32 case 0x00: /* SMR */
238bf5b7423Saurel32 ret = s->smr;
239bf5b7423Saurel32 break;
240bf5b7423Saurel32 case 0x08: /* SCR */
241bf5b7423Saurel32 ret = s->scr;
242bf5b7423Saurel32 break;
2432f062c72Sths case 0x10: /* FSR */
2442f062c72Sths ret = 0;
245ac3c9e74SBALATON Zoltan if (s->flags & SH_SERIAL_FLAG_TEND) {
2462f062c72Sths ret |= (1 << 6);
247ac3c9e74SBALATON Zoltan }
248ac3c9e74SBALATON Zoltan if (s->flags & SH_SERIAL_FLAG_TDE) {
2492f062c72Sths ret |= (1 << 5);
250ac3c9e74SBALATON Zoltan }
251ac3c9e74SBALATON Zoltan if (s->flags & SH_SERIAL_FLAG_BRK) {
2522f062c72Sths ret |= (1 << 4);
253ac3c9e74SBALATON Zoltan }
254ac3c9e74SBALATON Zoltan if (s->flags & SH_SERIAL_FLAG_RDF) {
2552f062c72Sths ret |= (1 << 1);
256ac3c9e74SBALATON Zoltan }
257ac3c9e74SBALATON Zoltan if (s->flags & SH_SERIAL_FLAG_DR) {
2582f062c72Sths ret |= (1 << 0);
259ac3c9e74SBALATON Zoltan }
2602f062c72Sths
261ac3c9e74SBALATON Zoltan if (s->scr & (1 << 5)) {
2622f062c72Sths s->flags |= SH_SERIAL_FLAG_TDE | SH_SERIAL_FLAG_TEND;
263ac3c9e74SBALATON Zoltan }
2642f062c72Sths
2652f062c72Sths break;
26663242a00Saurel32 case 0x14:
26763242a00Saurel32 if (s->rx_cnt > 0) {
26863242a00Saurel32 ret = s->rx_fifo[s->rx_tail++];
26963242a00Saurel32 s->rx_cnt--;
270ac3c9e74SBALATON Zoltan if (s->rx_tail == SH_RX_FIFO_LENGTH) {
27163242a00Saurel32 s->rx_tail = 0;
272ac3c9e74SBALATON Zoltan }
273ac3c9e74SBALATON Zoltan if (s->rx_cnt < s->rtrg) {
27463242a00Saurel32 s->flags &= ~SH_SERIAL_FLAG_RDF;
27563242a00Saurel32 }
276ac3c9e74SBALATON Zoltan }
27763242a00Saurel32 break;
2782f062c72Sths case 0x18:
2792f062c72Sths ret = s->fcr;
2802f062c72Sths break;
2812f062c72Sths case 0x1c:
2822f062c72Sths ret = s->rx_cnt;
2832f062c72Sths break;
2842f062c72Sths case 0x20:
2852f062c72Sths ret = s->sptr;
2862f062c72Sths break;
2872f062c72Sths case 0x24:
2882f062c72Sths ret = 0;
2892f062c72Sths break;
2902f062c72Sths }
291f94bff13SBALATON Zoltan } else {
2922f062c72Sths switch (offs) {
293d1f193b0Saurel32 #if 0
2942f062c72Sths case 0x0c:
2952f062c72Sths ret = s->dr;
2962f062c72Sths break;
2972f062c72Sths case 0x10:
2982f062c72Sths ret = 0;
2992f062c72Sths break;
30063242a00Saurel32 case 0x14:
30163242a00Saurel32 ret = s->rx_fifo[0];
30263242a00Saurel32 break;
303d1f193b0Saurel32 #endif
3042f062c72Sths case 0x1c:
3052f062c72Sths ret = s->sptr;
3062f062c72Sths break;
3072f062c72Sths }
3082f062c72Sths }
30944ae04f0SBALATON Zoltan trace_sh_serial_read(d->id, size, offs, ret);
3102f062c72Sths
3113cf7ce43SBALATON Zoltan if (ret > UINT16_MAX) {
3123cf7ce43SBALATON Zoltan qemu_log_mask(LOG_GUEST_ERROR,
3133cf7ce43SBALATON Zoltan "%s: unsupported read from 0x%02" HWADDR_PRIx "\n",
3143cf7ce43SBALATON Zoltan __func__, offs);
3153cf7ce43SBALATON Zoltan ret = 0;
3162f062c72Sths }
3172f062c72Sths
3182f062c72Sths return ret;
3192f062c72Sths }
3202f062c72Sths
sh_serial_can_receive(SHSerialState * s)3212f6df137SBALATON Zoltan static int sh_serial_can_receive(SHSerialState *s)
3222f062c72Sths {
323543671d9SPhilippe Mathieu-Daudé return s->scr & (1 << 4) ? SH_RX_FIFO_LENGTH - s->rx_head : 0;
3242f062c72Sths }
3252f062c72Sths
sh_serial_receive_break(SHSerialState * s)3262f6df137SBALATON Zoltan static void sh_serial_receive_break(SHSerialState *s)
3272f062c72Sths {
328ac3c9e74SBALATON Zoltan if (s->feat & SH_SERIAL_FEAT_SCIF) {
32963242a00Saurel32 s->sr |= (1 << 4);
3302f062c72Sths }
331ac3c9e74SBALATON Zoltan }
3322f062c72Sths
sh_serial_can_receive1(void * opaque)3332f062c72Sths static int sh_serial_can_receive1(void *opaque)
3342f062c72Sths {
3352f6df137SBALATON Zoltan SHSerialState *s = opaque;
3362f062c72Sths return sh_serial_can_receive(s);
3372f062c72Sths }
3382f062c72Sths
sh_serial_timeout_int(void * opaque)33971bb4ce1SGeert Uytterhoeven static void sh_serial_timeout_int(void *opaque)
34071bb4ce1SGeert Uytterhoeven {
3412f6df137SBALATON Zoltan SHSerialState *s = opaque;
34271bb4ce1SGeert Uytterhoeven
34371bb4ce1SGeert Uytterhoeven s->flags |= SH_SERIAL_FLAG_RDF;
34471bb4ce1SGeert Uytterhoeven if (s->scr & (1 << 6) && s->rxi) {
34571bb4ce1SGeert Uytterhoeven qemu_set_irq(s->rxi, 1);
34671bb4ce1SGeert Uytterhoeven }
34771bb4ce1SGeert Uytterhoeven }
34871bb4ce1SGeert Uytterhoeven
sh_serial_receive1(void * opaque,const uint8_t * buf,int size)3492f062c72Sths static void sh_serial_receive1(void *opaque, const uint8_t *buf, int size)
3502f062c72Sths {
3512f6df137SBALATON Zoltan SHSerialState *s = opaque;
352b7d2b020SAurelien Jarno
353b7d2b020SAurelien Jarno if (s->feat & SH_SERIAL_FEAT_SCIF) {
354b7d2b020SAurelien Jarno int i;
355b7d2b020SAurelien Jarno for (i = 0; i < size; i++) {
356b7d2b020SAurelien Jarno s->rx_fifo[s->rx_head++] = buf[i];
357b7d2b020SAurelien Jarno if (s->rx_head == SH_RX_FIFO_LENGTH) {
358b7d2b020SAurelien Jarno s->rx_head = 0;
359b7d2b020SAurelien Jarno }
360b7d2b020SAurelien Jarno s->rx_cnt++;
361b7d2b020SAurelien Jarno if (s->rx_cnt >= s->rtrg) {
362b7d2b020SAurelien Jarno s->flags |= SH_SERIAL_FLAG_RDF;
363b7d2b020SAurelien Jarno if (s->scr & (1 << 6) && s->rxi) {
3645b344b02SBALATON Zoltan timer_del(&s->fifo_timeout_timer);
365b7d2b020SAurelien Jarno qemu_set_irq(s->rxi, 1);
366b7d2b020SAurelien Jarno }
36771bb4ce1SGeert Uytterhoeven } else {
3685b344b02SBALATON Zoltan timer_mod(&s->fifo_timeout_timer,
36971bb4ce1SGeert Uytterhoeven qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + 15 * s->etu);
370b7d2b020SAurelien Jarno }
371b7d2b020SAurelien Jarno }
372b7d2b020SAurelien Jarno } else {
373b7d2b020SAurelien Jarno s->rx_fifo[0] = buf[0];
374b7d2b020SAurelien Jarno }
3752f062c72Sths }
3762f062c72Sths
sh_serial_event(void * opaque,QEMUChrEvent event)377083b266fSPhilippe Mathieu-Daudé static void sh_serial_event(void *opaque, QEMUChrEvent event)
3782f062c72Sths {
3792f6df137SBALATON Zoltan SHSerialState *s = opaque;
380ac3c9e74SBALATON Zoltan if (event == CHR_EVENT_BREAK) {
3812f062c72Sths sh_serial_receive_break(s);
3822f062c72Sths }
383ac3c9e74SBALATON Zoltan }
3842f062c72Sths
3859a9d0b81SBenoît Canet static const MemoryRegionOps sh_serial_ops = {
3869a9d0b81SBenoît Canet .read = sh_serial_read,
3879a9d0b81SBenoît Canet .write = sh_serial_write,
3889a9d0b81SBenoît Canet .endianness = DEVICE_NATIVE_ENDIAN,
3892f062c72Sths };
3902f062c72Sths
sh_serial_reset(DeviceState * dev)391beeb5209SBALATON Zoltan static void sh_serial_reset(DeviceState *dev)
392017f77bbSBALATON Zoltan {
393beeb5209SBALATON Zoltan SHSerialState *s = SH_SERIAL(dev);
394beeb5209SBALATON Zoltan
395017f77bbSBALATON Zoltan s->flags = SH_SERIAL_FLAG_TEND | SH_SERIAL_FLAG_TDE;
396017f77bbSBALATON Zoltan s->rtrg = 1;
397017f77bbSBALATON Zoltan
398017f77bbSBALATON Zoltan s->smr = 0;
399017f77bbSBALATON Zoltan s->brr = 0xff;
400017f77bbSBALATON Zoltan s->scr = 1 << 5; /* pretend that TX is enabled so early printk works */
401017f77bbSBALATON Zoltan s->sptr = 0;
402017f77bbSBALATON Zoltan
403017f77bbSBALATON Zoltan if (s->feat & SH_SERIAL_FEAT_SCIF) {
404017f77bbSBALATON Zoltan s->fcr = 0;
405017f77bbSBALATON Zoltan } else {
406017f77bbSBALATON Zoltan s->dr = 0xff;
407017f77bbSBALATON Zoltan }
408017f77bbSBALATON Zoltan
409017f77bbSBALATON Zoltan sh_serial_clear_fifo(s);
410017f77bbSBALATON Zoltan }
411017f77bbSBALATON Zoltan
sh_serial_realize(DeviceState * d,Error ** errp)412beeb5209SBALATON Zoltan static void sh_serial_realize(DeviceState *d, Error **errp)
4132f062c72Sths {
414beeb5209SBALATON Zoltan SHSerialState *s = SH_SERIAL(d);
415beeb5209SBALATON Zoltan MemoryRegion *iomem = g_malloc(sizeof(*iomem));
4162f062c72Sths
417beeb5209SBALATON Zoltan assert(d->id);
418beeb5209SBALATON Zoltan memory_region_init_io(iomem, OBJECT(d), &sh_serial_ops, s, d->id, 0x28);
419beeb5209SBALATON Zoltan sysbus_init_mmio(SYS_BUS_DEVICE(d), iomem);
420beeb5209SBALATON Zoltan qdev_init_gpio_out_named(d, &s->eri, "eri", 1);
421beeb5209SBALATON Zoltan qdev_init_gpio_out_named(d, &s->rxi, "rxi", 1);
422beeb5209SBALATON Zoltan qdev_init_gpio_out_named(d, &s->txi, "txi", 1);
423beeb5209SBALATON Zoltan qdev_init_gpio_out_named(d, &s->tei, "tei", 1);
424beeb5209SBALATON Zoltan qdev_init_gpio_out_named(d, &s->bri, "bri", 1);
4252f062c72Sths
426beeb5209SBALATON Zoltan if (qemu_chr_fe_backend_connected(&s->chr)) {
4275345fdb4SMarc-André Lureau qemu_chr_fe_set_handlers(&s->chr, sh_serial_can_receive1,
4285345fdb4SMarc-André Lureau sh_serial_receive1,
42981517ba3SAnton Nefedov sh_serial_event, NULL, s, NULL, true);
430456d6069SHans de Goede }
431bf5b7423Saurel32
4325b344b02SBALATON Zoltan timer_init_ns(&s->fifo_timeout_timer, QEMU_CLOCK_VIRTUAL,
43371bb4ce1SGeert Uytterhoeven sh_serial_timeout_int, s);
43471bb4ce1SGeert Uytterhoeven s->etu = NANOSECONDS_PER_SECOND / 9600;
435beeb5209SBALATON Zoltan }
436beeb5209SBALATON Zoltan
sh_serial_finalize(Object * obj)437beeb5209SBALATON Zoltan static void sh_serial_finalize(Object *obj)
438beeb5209SBALATON Zoltan {
439beeb5209SBALATON Zoltan SHSerialState *s = SH_SERIAL(obj);
440beeb5209SBALATON Zoltan
441beeb5209SBALATON Zoltan timer_del(&s->fifo_timeout_timer);
442beeb5209SBALATON Zoltan }
443beeb5209SBALATON Zoltan
sh_serial_init(Object * obj)444beeb5209SBALATON Zoltan static void sh_serial_init(Object *obj)
445beeb5209SBALATON Zoltan {
446beeb5209SBALATON Zoltan }
447beeb5209SBALATON Zoltan
448312f37d1SRichard Henderson static const Property sh_serial_properties[] = {
449beeb5209SBALATON Zoltan DEFINE_PROP_CHR("chardev", SHSerialState, chr),
450beeb5209SBALATON Zoltan DEFINE_PROP_UINT8("features", SHSerialState, feat, 0),
451beeb5209SBALATON Zoltan };
452beeb5209SBALATON Zoltan
sh_serial_class_init(ObjectClass * oc,const void * data)453*12d1a768SPhilippe Mathieu-Daudé static void sh_serial_class_init(ObjectClass *oc, const void *data)
454beeb5209SBALATON Zoltan {
455beeb5209SBALATON Zoltan DeviceClass *dc = DEVICE_CLASS(oc);
456beeb5209SBALATON Zoltan
457beeb5209SBALATON Zoltan device_class_set_props(dc, sh_serial_properties);
458beeb5209SBALATON Zoltan dc->realize = sh_serial_realize;
459e3d08143SPeter Maydell device_class_set_legacy_reset(dc, sh_serial_reset);
460beeb5209SBALATON Zoltan /* Reason: part of SuperH CPU/SoC, needs to be wired up */
461beeb5209SBALATON Zoltan dc->user_creatable = false;
4622f062c72Sths }
463