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 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 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 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 3212f6df137SBALATON Zoltan static int sh_serial_can_receive(SHSerialState *s) 3222f062c72Sths { 32363242a00Saurel32 return s->scr & (1 << 4); 3242f062c72Sths } 3252f062c72Sths 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 3332f062c72Sths static int sh_serial_can_receive1(void *opaque) 3342f062c72Sths { 3352f6df137SBALATON Zoltan SHSerialState *s = opaque; 3362f062c72Sths return sh_serial_can_receive(s); 3372f062c72Sths } 3382f062c72Sths 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 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 if (s->rx_cnt < SH_RX_FIFO_LENGTH) { 357b7d2b020SAurelien Jarno s->rx_fifo[s->rx_head++] = buf[i]; 358b7d2b020SAurelien Jarno if (s->rx_head == SH_RX_FIFO_LENGTH) { 359b7d2b020SAurelien Jarno s->rx_head = 0; 360b7d2b020SAurelien Jarno } 361b7d2b020SAurelien Jarno s->rx_cnt++; 362b7d2b020SAurelien Jarno if (s->rx_cnt >= s->rtrg) { 363b7d2b020SAurelien Jarno s->flags |= SH_SERIAL_FLAG_RDF; 364b7d2b020SAurelien Jarno if (s->scr & (1 << 6) && s->rxi) { 3655b344b02SBALATON Zoltan timer_del(&s->fifo_timeout_timer); 366b7d2b020SAurelien Jarno qemu_set_irq(s->rxi, 1); 367b7d2b020SAurelien Jarno } 36871bb4ce1SGeert Uytterhoeven } else { 3695b344b02SBALATON Zoltan timer_mod(&s->fifo_timeout_timer, 37071bb4ce1SGeert Uytterhoeven qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + 15 * s->etu); 371b7d2b020SAurelien Jarno } 372b7d2b020SAurelien Jarno } 373b7d2b020SAurelien Jarno } 374b7d2b020SAurelien Jarno } else { 375b7d2b020SAurelien Jarno s->rx_fifo[0] = buf[0]; 376b7d2b020SAurelien Jarno } 3772f062c72Sths } 3782f062c72Sths 379083b266fSPhilippe Mathieu-Daudé static void sh_serial_event(void *opaque, QEMUChrEvent event) 3802f062c72Sths { 3812f6df137SBALATON Zoltan SHSerialState *s = opaque; 382ac3c9e74SBALATON Zoltan if (event == CHR_EVENT_BREAK) { 3832f062c72Sths sh_serial_receive_break(s); 3842f062c72Sths } 385ac3c9e74SBALATON Zoltan } 3862f062c72Sths 3879a9d0b81SBenoît Canet static const MemoryRegionOps sh_serial_ops = { 3889a9d0b81SBenoît Canet .read = sh_serial_read, 3899a9d0b81SBenoît Canet .write = sh_serial_write, 3909a9d0b81SBenoît Canet .endianness = DEVICE_NATIVE_ENDIAN, 3912f062c72Sths }; 3922f062c72Sths 393beeb5209SBALATON Zoltan static void sh_serial_reset(DeviceState *dev) 394017f77bbSBALATON Zoltan { 395beeb5209SBALATON Zoltan SHSerialState *s = SH_SERIAL(dev); 396beeb5209SBALATON Zoltan 397017f77bbSBALATON Zoltan s->flags = SH_SERIAL_FLAG_TEND | SH_SERIAL_FLAG_TDE; 398017f77bbSBALATON Zoltan s->rtrg = 1; 399017f77bbSBALATON Zoltan 400017f77bbSBALATON Zoltan s->smr = 0; 401017f77bbSBALATON Zoltan s->brr = 0xff; 402017f77bbSBALATON Zoltan s->scr = 1 << 5; /* pretend that TX is enabled so early printk works */ 403017f77bbSBALATON Zoltan s->sptr = 0; 404017f77bbSBALATON Zoltan 405017f77bbSBALATON Zoltan if (s->feat & SH_SERIAL_FEAT_SCIF) { 406017f77bbSBALATON Zoltan s->fcr = 0; 407017f77bbSBALATON Zoltan } else { 408017f77bbSBALATON Zoltan s->dr = 0xff; 409017f77bbSBALATON Zoltan } 410017f77bbSBALATON Zoltan 411017f77bbSBALATON Zoltan sh_serial_clear_fifo(s); 412017f77bbSBALATON Zoltan } 413017f77bbSBALATON Zoltan 414beeb5209SBALATON Zoltan static void sh_serial_realize(DeviceState *d, Error **errp) 4152f062c72Sths { 416beeb5209SBALATON Zoltan SHSerialState *s = SH_SERIAL(d); 417beeb5209SBALATON Zoltan MemoryRegion *iomem = g_malloc(sizeof(*iomem)); 4182f062c72Sths 419beeb5209SBALATON Zoltan assert(d->id); 420beeb5209SBALATON Zoltan memory_region_init_io(iomem, OBJECT(d), &sh_serial_ops, s, d->id, 0x28); 421beeb5209SBALATON Zoltan sysbus_init_mmio(SYS_BUS_DEVICE(d), iomem); 422beeb5209SBALATON Zoltan qdev_init_gpio_out_named(d, &s->eri, "eri", 1); 423beeb5209SBALATON Zoltan qdev_init_gpio_out_named(d, &s->rxi, "rxi", 1); 424beeb5209SBALATON Zoltan qdev_init_gpio_out_named(d, &s->txi, "txi", 1); 425beeb5209SBALATON Zoltan qdev_init_gpio_out_named(d, &s->tei, "tei", 1); 426beeb5209SBALATON Zoltan qdev_init_gpio_out_named(d, &s->bri, "bri", 1); 4272f062c72Sths 428beeb5209SBALATON Zoltan if (qemu_chr_fe_backend_connected(&s->chr)) { 4295345fdb4SMarc-André Lureau qemu_chr_fe_set_handlers(&s->chr, sh_serial_can_receive1, 4305345fdb4SMarc-André Lureau sh_serial_receive1, 43181517ba3SAnton Nefedov sh_serial_event, NULL, s, NULL, true); 432456d6069SHans de Goede } 433bf5b7423Saurel32 4345b344b02SBALATON Zoltan timer_init_ns(&s->fifo_timeout_timer, QEMU_CLOCK_VIRTUAL, 43571bb4ce1SGeert Uytterhoeven sh_serial_timeout_int, s); 43671bb4ce1SGeert Uytterhoeven s->etu = NANOSECONDS_PER_SECOND / 9600; 437beeb5209SBALATON Zoltan } 438beeb5209SBALATON Zoltan 439beeb5209SBALATON Zoltan static void sh_serial_finalize(Object *obj) 440beeb5209SBALATON Zoltan { 441beeb5209SBALATON Zoltan SHSerialState *s = SH_SERIAL(obj); 442beeb5209SBALATON Zoltan 443beeb5209SBALATON Zoltan timer_del(&s->fifo_timeout_timer); 444beeb5209SBALATON Zoltan } 445beeb5209SBALATON Zoltan 446beeb5209SBALATON Zoltan static void sh_serial_init(Object *obj) 447beeb5209SBALATON Zoltan { 448beeb5209SBALATON Zoltan } 449beeb5209SBALATON Zoltan 450beeb5209SBALATON Zoltan static Property sh_serial_properties[] = { 451beeb5209SBALATON Zoltan DEFINE_PROP_CHR("chardev", SHSerialState, chr), 452beeb5209SBALATON Zoltan DEFINE_PROP_UINT8("features", SHSerialState, feat, 0), 453beeb5209SBALATON Zoltan DEFINE_PROP_END_OF_LIST() 454beeb5209SBALATON Zoltan }; 455beeb5209SBALATON Zoltan 456beeb5209SBALATON Zoltan static void sh_serial_class_init(ObjectClass *oc, void *data) 457beeb5209SBALATON Zoltan { 458beeb5209SBALATON Zoltan DeviceClass *dc = DEVICE_CLASS(oc); 459beeb5209SBALATON Zoltan 460beeb5209SBALATON Zoltan device_class_set_props(dc, sh_serial_properties); 461beeb5209SBALATON Zoltan dc->realize = sh_serial_realize; 462*e3d08143SPeter Maydell device_class_set_legacy_reset(dc, sh_serial_reset); 463beeb5209SBALATON Zoltan /* Reason: part of SuperH CPU/SoC, needs to be wired up */ 464beeb5209SBALATON Zoltan dc->user_creatable = false; 4652f062c72Sths } 466