19944d320SPaolo Bonzini /* 29944d320SPaolo Bonzini * QEMU SCI/SCIF serial port emulation 39944d320SPaolo Bonzini * 49944d320SPaolo Bonzini * Copyright (c) 2007 Magnus Damm 59944d320SPaolo Bonzini * 69944d320SPaolo Bonzini * Based on serial.c - QEMU 16450 UART emulation 79944d320SPaolo Bonzini * Copyright (c) 2003-2004 Fabrice Bellard 89944d320SPaolo Bonzini * 99944d320SPaolo Bonzini * Permission is hereby granted, free of charge, to any person obtaining a copy 109944d320SPaolo Bonzini * of this software and associated documentation files (the "Software"), to deal 119944d320SPaolo Bonzini * in the Software without restriction, including without limitation the rights 129944d320SPaolo Bonzini * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 139944d320SPaolo Bonzini * copies of the Software, and to permit persons to whom the Software is 149944d320SPaolo Bonzini * furnished to do so, subject to the following conditions: 159944d320SPaolo Bonzini * 169944d320SPaolo Bonzini * The above copyright notice and this permission notice shall be included in 179944d320SPaolo Bonzini * all copies or substantial portions of the Software. 189944d320SPaolo Bonzini * 199944d320SPaolo Bonzini * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 209944d320SPaolo Bonzini * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 219944d320SPaolo Bonzini * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 229944d320SPaolo Bonzini * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 239944d320SPaolo Bonzini * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 249944d320SPaolo Bonzini * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 259944d320SPaolo Bonzini * THE SOFTWARE. 269944d320SPaolo Bonzini */ 279944d320SPaolo Bonzini #include "hw/hw.h" 289944d320SPaolo Bonzini #include "hw/sh4/sh.h" 29*dccfcd0eSPaolo Bonzini #include "sysemu/char.h" 309944d320SPaolo Bonzini #include "exec/address-spaces.h" 319944d320SPaolo Bonzini 329944d320SPaolo Bonzini //#define DEBUG_SERIAL 339944d320SPaolo Bonzini 349944d320SPaolo Bonzini #define SH_SERIAL_FLAG_TEND (1 << 0) 359944d320SPaolo Bonzini #define SH_SERIAL_FLAG_TDE (1 << 1) 369944d320SPaolo Bonzini #define SH_SERIAL_FLAG_RDF (1 << 2) 379944d320SPaolo Bonzini #define SH_SERIAL_FLAG_BRK (1 << 3) 389944d320SPaolo Bonzini #define SH_SERIAL_FLAG_DR (1 << 4) 399944d320SPaolo Bonzini 409944d320SPaolo Bonzini #define SH_RX_FIFO_LENGTH (16) 419944d320SPaolo Bonzini 429944d320SPaolo Bonzini typedef struct { 439944d320SPaolo Bonzini MemoryRegion iomem; 449944d320SPaolo Bonzini MemoryRegion iomem_p4; 459944d320SPaolo Bonzini MemoryRegion iomem_a7; 469944d320SPaolo Bonzini uint8_t smr; 479944d320SPaolo Bonzini uint8_t brr; 489944d320SPaolo Bonzini uint8_t scr; 499944d320SPaolo Bonzini uint8_t dr; /* ftdr / tdr */ 509944d320SPaolo Bonzini uint8_t sr; /* fsr / ssr */ 519944d320SPaolo Bonzini uint16_t fcr; 529944d320SPaolo Bonzini uint8_t sptr; 539944d320SPaolo Bonzini 549944d320SPaolo Bonzini uint8_t rx_fifo[SH_RX_FIFO_LENGTH]; /* frdr / rdr */ 559944d320SPaolo Bonzini uint8_t rx_cnt; 569944d320SPaolo Bonzini uint8_t rx_tail; 579944d320SPaolo Bonzini uint8_t rx_head; 589944d320SPaolo Bonzini 599944d320SPaolo Bonzini int freq; 609944d320SPaolo Bonzini int feat; 619944d320SPaolo Bonzini int flags; 629944d320SPaolo Bonzini int rtrg; 639944d320SPaolo Bonzini 649944d320SPaolo Bonzini CharDriverState *chr; 659944d320SPaolo Bonzini 669944d320SPaolo Bonzini qemu_irq eri; 679944d320SPaolo Bonzini qemu_irq rxi; 689944d320SPaolo Bonzini qemu_irq txi; 699944d320SPaolo Bonzini qemu_irq tei; 709944d320SPaolo Bonzini qemu_irq bri; 719944d320SPaolo Bonzini } sh_serial_state; 729944d320SPaolo Bonzini 739944d320SPaolo Bonzini static void sh_serial_clear_fifo(sh_serial_state * s) 749944d320SPaolo Bonzini { 759944d320SPaolo Bonzini memset(s->rx_fifo, 0, SH_RX_FIFO_LENGTH); 769944d320SPaolo Bonzini s->rx_cnt = 0; 779944d320SPaolo Bonzini s->rx_head = 0; 789944d320SPaolo Bonzini s->rx_tail = 0; 799944d320SPaolo Bonzini } 809944d320SPaolo Bonzini 819944d320SPaolo Bonzini static void sh_serial_write(void *opaque, hwaddr offs, 829944d320SPaolo Bonzini uint64_t val, unsigned size) 839944d320SPaolo Bonzini { 849944d320SPaolo Bonzini sh_serial_state *s = opaque; 859944d320SPaolo Bonzini unsigned char ch; 869944d320SPaolo Bonzini 879944d320SPaolo Bonzini #ifdef DEBUG_SERIAL 889944d320SPaolo Bonzini printf("sh_serial: write offs=0x%02x val=0x%02x\n", 899944d320SPaolo Bonzini offs, val); 909944d320SPaolo Bonzini #endif 919944d320SPaolo Bonzini switch(offs) { 929944d320SPaolo Bonzini case 0x00: /* SMR */ 939944d320SPaolo Bonzini s->smr = val & ((s->feat & SH_SERIAL_FEAT_SCIF) ? 0x7b : 0xff); 949944d320SPaolo Bonzini return; 959944d320SPaolo Bonzini case 0x04: /* BRR */ 969944d320SPaolo Bonzini s->brr = val; 979944d320SPaolo Bonzini return; 989944d320SPaolo Bonzini case 0x08: /* SCR */ 999944d320SPaolo Bonzini /* TODO : For SH7751, SCIF mask should be 0xfb. */ 1009944d320SPaolo Bonzini s->scr = val & ((s->feat & SH_SERIAL_FEAT_SCIF) ? 0xfa : 0xff); 1019944d320SPaolo Bonzini if (!(val & (1 << 5))) 1029944d320SPaolo Bonzini s->flags |= SH_SERIAL_FLAG_TEND; 1039944d320SPaolo Bonzini if ((s->feat & SH_SERIAL_FEAT_SCIF) && s->txi) { 1049944d320SPaolo Bonzini qemu_set_irq(s->txi, val & (1 << 7)); 1059944d320SPaolo Bonzini } 1069944d320SPaolo Bonzini if (!(val & (1 << 6))) { 1079944d320SPaolo Bonzini qemu_set_irq(s->rxi, 0); 1089944d320SPaolo Bonzini } 1099944d320SPaolo Bonzini return; 1109944d320SPaolo Bonzini case 0x0c: /* FTDR / TDR */ 1119944d320SPaolo Bonzini if (s->chr) { 1129944d320SPaolo Bonzini ch = val; 1139944d320SPaolo Bonzini qemu_chr_fe_write(s->chr, &ch, 1); 1149944d320SPaolo Bonzini } 1159944d320SPaolo Bonzini s->dr = val; 1169944d320SPaolo Bonzini s->flags &= ~SH_SERIAL_FLAG_TDE; 1179944d320SPaolo Bonzini return; 1189944d320SPaolo Bonzini #if 0 1199944d320SPaolo Bonzini case 0x14: /* FRDR / RDR */ 1209944d320SPaolo Bonzini ret = 0; 1219944d320SPaolo Bonzini break; 1229944d320SPaolo Bonzini #endif 1239944d320SPaolo Bonzini } 1249944d320SPaolo Bonzini if (s->feat & SH_SERIAL_FEAT_SCIF) { 1259944d320SPaolo Bonzini switch(offs) { 1269944d320SPaolo Bonzini case 0x10: /* FSR */ 1279944d320SPaolo Bonzini if (!(val & (1 << 6))) 1289944d320SPaolo Bonzini s->flags &= ~SH_SERIAL_FLAG_TEND; 1299944d320SPaolo Bonzini if (!(val & (1 << 5))) 1309944d320SPaolo Bonzini s->flags &= ~SH_SERIAL_FLAG_TDE; 1319944d320SPaolo Bonzini if (!(val & (1 << 4))) 1329944d320SPaolo Bonzini s->flags &= ~SH_SERIAL_FLAG_BRK; 1339944d320SPaolo Bonzini if (!(val & (1 << 1))) 1349944d320SPaolo Bonzini s->flags &= ~SH_SERIAL_FLAG_RDF; 1359944d320SPaolo Bonzini if (!(val & (1 << 0))) 1369944d320SPaolo Bonzini s->flags &= ~SH_SERIAL_FLAG_DR; 1379944d320SPaolo Bonzini 1389944d320SPaolo Bonzini if (!(val & (1 << 1)) || !(val & (1 << 0))) { 1399944d320SPaolo Bonzini if (s->rxi) { 1409944d320SPaolo Bonzini qemu_set_irq(s->rxi, 0); 1419944d320SPaolo Bonzini } 1429944d320SPaolo Bonzini } 1439944d320SPaolo Bonzini return; 1449944d320SPaolo Bonzini case 0x18: /* FCR */ 1459944d320SPaolo Bonzini s->fcr = val; 1469944d320SPaolo Bonzini switch ((val >> 6) & 3) { 1479944d320SPaolo Bonzini case 0: 1489944d320SPaolo Bonzini s->rtrg = 1; 1499944d320SPaolo Bonzini break; 1509944d320SPaolo Bonzini case 1: 1519944d320SPaolo Bonzini s->rtrg = 4; 1529944d320SPaolo Bonzini break; 1539944d320SPaolo Bonzini case 2: 1549944d320SPaolo Bonzini s->rtrg = 8; 1559944d320SPaolo Bonzini break; 1569944d320SPaolo Bonzini case 3: 1579944d320SPaolo Bonzini s->rtrg = 14; 1589944d320SPaolo Bonzini break; 1599944d320SPaolo Bonzini } 1609944d320SPaolo Bonzini if (val & (1 << 1)) { 1619944d320SPaolo Bonzini sh_serial_clear_fifo(s); 1629944d320SPaolo Bonzini s->sr &= ~(1 << 1); 1639944d320SPaolo Bonzini } 1649944d320SPaolo Bonzini 1659944d320SPaolo Bonzini return; 1669944d320SPaolo Bonzini case 0x20: /* SPTR */ 1679944d320SPaolo Bonzini s->sptr = val & 0xf3; 1689944d320SPaolo Bonzini return; 1699944d320SPaolo Bonzini case 0x24: /* LSR */ 1709944d320SPaolo Bonzini return; 1719944d320SPaolo Bonzini } 1729944d320SPaolo Bonzini } 1739944d320SPaolo Bonzini else { 1749944d320SPaolo Bonzini switch(offs) { 1759944d320SPaolo Bonzini #if 0 1769944d320SPaolo Bonzini case 0x0c: 1779944d320SPaolo Bonzini ret = s->dr; 1789944d320SPaolo Bonzini break; 1799944d320SPaolo Bonzini case 0x10: 1809944d320SPaolo Bonzini ret = 0; 1819944d320SPaolo Bonzini break; 1829944d320SPaolo Bonzini #endif 1839944d320SPaolo Bonzini case 0x1c: 1849944d320SPaolo Bonzini s->sptr = val & 0x8f; 1859944d320SPaolo Bonzini return; 1869944d320SPaolo Bonzini } 1879944d320SPaolo Bonzini } 1889944d320SPaolo Bonzini 1899944d320SPaolo Bonzini fprintf(stderr, "sh_serial: unsupported write to 0x%02" 1909944d320SPaolo Bonzini HWADDR_PRIx "\n", offs); 1919944d320SPaolo Bonzini abort(); 1929944d320SPaolo Bonzini } 1939944d320SPaolo Bonzini 1949944d320SPaolo Bonzini static uint64_t sh_serial_read(void *opaque, hwaddr offs, 1959944d320SPaolo Bonzini unsigned size) 1969944d320SPaolo Bonzini { 1979944d320SPaolo Bonzini sh_serial_state *s = opaque; 1989944d320SPaolo Bonzini uint32_t ret = ~0; 1999944d320SPaolo Bonzini 2009944d320SPaolo Bonzini #if 0 2019944d320SPaolo Bonzini switch(offs) { 2029944d320SPaolo Bonzini case 0x00: 2039944d320SPaolo Bonzini ret = s->smr; 2049944d320SPaolo Bonzini break; 2059944d320SPaolo Bonzini case 0x04: 2069944d320SPaolo Bonzini ret = s->brr; 2079944d320SPaolo Bonzini break; 2089944d320SPaolo Bonzini case 0x08: 2099944d320SPaolo Bonzini ret = s->scr; 2109944d320SPaolo Bonzini break; 2119944d320SPaolo Bonzini case 0x14: 2129944d320SPaolo Bonzini ret = 0; 2139944d320SPaolo Bonzini break; 2149944d320SPaolo Bonzini } 2159944d320SPaolo Bonzini #endif 2169944d320SPaolo Bonzini if (s->feat & SH_SERIAL_FEAT_SCIF) { 2179944d320SPaolo Bonzini switch(offs) { 2189944d320SPaolo Bonzini case 0x00: /* SMR */ 2199944d320SPaolo Bonzini ret = s->smr; 2209944d320SPaolo Bonzini break; 2219944d320SPaolo Bonzini case 0x08: /* SCR */ 2229944d320SPaolo Bonzini ret = s->scr; 2239944d320SPaolo Bonzini break; 2249944d320SPaolo Bonzini case 0x10: /* FSR */ 2259944d320SPaolo Bonzini ret = 0; 2269944d320SPaolo Bonzini if (s->flags & SH_SERIAL_FLAG_TEND) 2279944d320SPaolo Bonzini ret |= (1 << 6); 2289944d320SPaolo Bonzini if (s->flags & SH_SERIAL_FLAG_TDE) 2299944d320SPaolo Bonzini ret |= (1 << 5); 2309944d320SPaolo Bonzini if (s->flags & SH_SERIAL_FLAG_BRK) 2319944d320SPaolo Bonzini ret |= (1 << 4); 2329944d320SPaolo Bonzini if (s->flags & SH_SERIAL_FLAG_RDF) 2339944d320SPaolo Bonzini ret |= (1 << 1); 2349944d320SPaolo Bonzini if (s->flags & SH_SERIAL_FLAG_DR) 2359944d320SPaolo Bonzini ret |= (1 << 0); 2369944d320SPaolo Bonzini 2379944d320SPaolo Bonzini if (s->scr & (1 << 5)) 2389944d320SPaolo Bonzini s->flags |= SH_SERIAL_FLAG_TDE | SH_SERIAL_FLAG_TEND; 2399944d320SPaolo Bonzini 2409944d320SPaolo Bonzini break; 2419944d320SPaolo Bonzini case 0x14: 2429944d320SPaolo Bonzini if (s->rx_cnt > 0) { 2439944d320SPaolo Bonzini ret = s->rx_fifo[s->rx_tail++]; 2449944d320SPaolo Bonzini s->rx_cnt--; 2459944d320SPaolo Bonzini if (s->rx_tail == SH_RX_FIFO_LENGTH) 2469944d320SPaolo Bonzini s->rx_tail = 0; 2479944d320SPaolo Bonzini if (s->rx_cnt < s->rtrg) 2489944d320SPaolo Bonzini s->flags &= ~SH_SERIAL_FLAG_RDF; 2499944d320SPaolo Bonzini } 2509944d320SPaolo Bonzini break; 2519944d320SPaolo Bonzini #if 0 2529944d320SPaolo Bonzini case 0x18: 2539944d320SPaolo Bonzini ret = s->fcr; 2549944d320SPaolo Bonzini break; 2559944d320SPaolo Bonzini #endif 2569944d320SPaolo Bonzini case 0x1c: 2579944d320SPaolo Bonzini ret = s->rx_cnt; 2589944d320SPaolo Bonzini break; 2599944d320SPaolo Bonzini case 0x20: 2609944d320SPaolo Bonzini ret = s->sptr; 2619944d320SPaolo Bonzini break; 2629944d320SPaolo Bonzini case 0x24: 2639944d320SPaolo Bonzini ret = 0; 2649944d320SPaolo Bonzini break; 2659944d320SPaolo Bonzini } 2669944d320SPaolo Bonzini } 2679944d320SPaolo Bonzini else { 2689944d320SPaolo Bonzini switch(offs) { 2699944d320SPaolo Bonzini #if 0 2709944d320SPaolo Bonzini case 0x0c: 2719944d320SPaolo Bonzini ret = s->dr; 2729944d320SPaolo Bonzini break; 2739944d320SPaolo Bonzini case 0x10: 2749944d320SPaolo Bonzini ret = 0; 2759944d320SPaolo Bonzini break; 2769944d320SPaolo Bonzini case 0x14: 2779944d320SPaolo Bonzini ret = s->rx_fifo[0]; 2789944d320SPaolo Bonzini break; 2799944d320SPaolo Bonzini #endif 2809944d320SPaolo Bonzini case 0x1c: 2819944d320SPaolo Bonzini ret = s->sptr; 2829944d320SPaolo Bonzini break; 2839944d320SPaolo Bonzini } 2849944d320SPaolo Bonzini } 2859944d320SPaolo Bonzini #ifdef DEBUG_SERIAL 2869944d320SPaolo Bonzini printf("sh_serial: read offs=0x%02x val=0x%x\n", 2879944d320SPaolo Bonzini offs, ret); 2889944d320SPaolo Bonzini #endif 2899944d320SPaolo Bonzini 2909944d320SPaolo Bonzini if (ret & ~((1 << 16) - 1)) { 2919944d320SPaolo Bonzini fprintf(stderr, "sh_serial: unsupported read from 0x%02" 2929944d320SPaolo Bonzini HWADDR_PRIx "\n", offs); 2939944d320SPaolo Bonzini abort(); 2949944d320SPaolo Bonzini } 2959944d320SPaolo Bonzini 2969944d320SPaolo Bonzini return ret; 2979944d320SPaolo Bonzini } 2989944d320SPaolo Bonzini 2999944d320SPaolo Bonzini static int sh_serial_can_receive(sh_serial_state *s) 3009944d320SPaolo Bonzini { 3019944d320SPaolo Bonzini return s->scr & (1 << 4); 3029944d320SPaolo Bonzini } 3039944d320SPaolo Bonzini 3049944d320SPaolo Bonzini static void sh_serial_receive_break(sh_serial_state *s) 3059944d320SPaolo Bonzini { 3069944d320SPaolo Bonzini if (s->feat & SH_SERIAL_FEAT_SCIF) 3079944d320SPaolo Bonzini s->sr |= (1 << 4); 3089944d320SPaolo Bonzini } 3099944d320SPaolo Bonzini 3109944d320SPaolo Bonzini static int sh_serial_can_receive1(void *opaque) 3119944d320SPaolo Bonzini { 3129944d320SPaolo Bonzini sh_serial_state *s = opaque; 3139944d320SPaolo Bonzini return sh_serial_can_receive(s); 3149944d320SPaolo Bonzini } 3159944d320SPaolo Bonzini 3169944d320SPaolo Bonzini static void sh_serial_receive1(void *opaque, const uint8_t *buf, int size) 3179944d320SPaolo Bonzini { 3189944d320SPaolo Bonzini sh_serial_state *s = opaque; 3199944d320SPaolo Bonzini 3209944d320SPaolo Bonzini if (s->feat & SH_SERIAL_FEAT_SCIF) { 3219944d320SPaolo Bonzini int i; 3229944d320SPaolo Bonzini for (i = 0; i < size; i++) { 3239944d320SPaolo Bonzini if (s->rx_cnt < SH_RX_FIFO_LENGTH) { 3249944d320SPaolo Bonzini s->rx_fifo[s->rx_head++] = buf[i]; 3259944d320SPaolo Bonzini if (s->rx_head == SH_RX_FIFO_LENGTH) { 3269944d320SPaolo Bonzini s->rx_head = 0; 3279944d320SPaolo Bonzini } 3289944d320SPaolo Bonzini s->rx_cnt++; 3299944d320SPaolo Bonzini if (s->rx_cnt >= s->rtrg) { 3309944d320SPaolo Bonzini s->flags |= SH_SERIAL_FLAG_RDF; 3319944d320SPaolo Bonzini if (s->scr & (1 << 6) && s->rxi) { 3329944d320SPaolo Bonzini qemu_set_irq(s->rxi, 1); 3339944d320SPaolo Bonzini } 3349944d320SPaolo Bonzini } 3359944d320SPaolo Bonzini } 3369944d320SPaolo Bonzini } 3379944d320SPaolo Bonzini } else { 3389944d320SPaolo Bonzini s->rx_fifo[0] = buf[0]; 3399944d320SPaolo Bonzini } 3409944d320SPaolo Bonzini } 3419944d320SPaolo Bonzini 3429944d320SPaolo Bonzini static void sh_serial_event(void *opaque, int event) 3439944d320SPaolo Bonzini { 3449944d320SPaolo Bonzini sh_serial_state *s = opaque; 3459944d320SPaolo Bonzini if (event == CHR_EVENT_BREAK) 3469944d320SPaolo Bonzini sh_serial_receive_break(s); 3479944d320SPaolo Bonzini } 3489944d320SPaolo Bonzini 3499944d320SPaolo Bonzini static const MemoryRegionOps sh_serial_ops = { 3509944d320SPaolo Bonzini .read = sh_serial_read, 3519944d320SPaolo Bonzini .write = sh_serial_write, 3529944d320SPaolo Bonzini .endianness = DEVICE_NATIVE_ENDIAN, 3539944d320SPaolo Bonzini }; 3549944d320SPaolo Bonzini 3559944d320SPaolo Bonzini void sh_serial_init(MemoryRegion *sysmem, 3569944d320SPaolo Bonzini hwaddr base, int feat, 3579944d320SPaolo Bonzini uint32_t freq, CharDriverState *chr, 3589944d320SPaolo Bonzini qemu_irq eri_source, 3599944d320SPaolo Bonzini qemu_irq rxi_source, 3609944d320SPaolo Bonzini qemu_irq txi_source, 3619944d320SPaolo Bonzini qemu_irq tei_source, 3629944d320SPaolo Bonzini qemu_irq bri_source) 3639944d320SPaolo Bonzini { 3649944d320SPaolo Bonzini sh_serial_state *s; 3659944d320SPaolo Bonzini 3669944d320SPaolo Bonzini s = g_malloc0(sizeof(sh_serial_state)); 3679944d320SPaolo Bonzini 3689944d320SPaolo Bonzini s->feat = feat; 3699944d320SPaolo Bonzini s->flags = SH_SERIAL_FLAG_TEND | SH_SERIAL_FLAG_TDE; 3709944d320SPaolo Bonzini s->rtrg = 1; 3719944d320SPaolo Bonzini 3729944d320SPaolo Bonzini s->smr = 0; 3739944d320SPaolo Bonzini s->brr = 0xff; 3749944d320SPaolo Bonzini s->scr = 1 << 5; /* pretend that TX is enabled so early printk works */ 3759944d320SPaolo Bonzini s->sptr = 0; 3769944d320SPaolo Bonzini 3779944d320SPaolo Bonzini if (feat & SH_SERIAL_FEAT_SCIF) { 3789944d320SPaolo Bonzini s->fcr = 0; 3799944d320SPaolo Bonzini } 3809944d320SPaolo Bonzini else { 3819944d320SPaolo Bonzini s->dr = 0xff; 3829944d320SPaolo Bonzini } 3839944d320SPaolo Bonzini 3849944d320SPaolo Bonzini sh_serial_clear_fifo(s); 3859944d320SPaolo Bonzini 3869944d320SPaolo Bonzini memory_region_init_io(&s->iomem, &sh_serial_ops, s, 3879944d320SPaolo Bonzini "serial", 0x100000000ULL); 3889944d320SPaolo Bonzini 3899944d320SPaolo Bonzini memory_region_init_alias(&s->iomem_p4, "serial-p4", &s->iomem, 3909944d320SPaolo Bonzini 0, 0x28); 3919944d320SPaolo Bonzini memory_region_add_subregion(sysmem, P4ADDR(base), &s->iomem_p4); 3929944d320SPaolo Bonzini 3939944d320SPaolo Bonzini memory_region_init_alias(&s->iomem_a7, "serial-a7", &s->iomem, 3949944d320SPaolo Bonzini 0, 0x28); 3959944d320SPaolo Bonzini memory_region_add_subregion(sysmem, A7ADDR(base), &s->iomem_a7); 3969944d320SPaolo Bonzini 3979944d320SPaolo Bonzini s->chr = chr; 3989944d320SPaolo Bonzini 3999944d320SPaolo Bonzini if (chr) { 4009944d320SPaolo Bonzini qemu_chr_fe_claim_no_fail(chr); 4019944d320SPaolo Bonzini qemu_chr_add_handlers(chr, sh_serial_can_receive1, sh_serial_receive1, 4029944d320SPaolo Bonzini sh_serial_event, s); 4039944d320SPaolo Bonzini } 4049944d320SPaolo Bonzini 4059944d320SPaolo Bonzini s->eri = eri_source; 4069944d320SPaolo Bonzini s->rxi = rxi_source; 4079944d320SPaolo Bonzini s->txi = txi_source; 4089944d320SPaolo Bonzini s->tei = tei_source; 4099944d320SPaolo Bonzini s->bri = bri_source; 4109944d320SPaolo Bonzini } 411