qemu

FORK: QEMU emulator
git clone https://git.neptards.moe/neptards/qemu.git
Log | Files | Refs | Submodules | LICENSE

grlib_apbuart.c (8355B)


      1 /*
      2  * QEMU GRLIB APB UART Emulator
      3  *
      4  * Copyright (c) 2010-2019 AdaCore
      5  *
      6  * Permission is hereby granted, free of charge, to any person obtaining a copy
      7  * of this software and associated documentation files (the "Software"), to deal
      8  * in the Software without restriction, including without limitation the rights
      9  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
     10  * copies of the Software, and to permit persons to whom the Software is
     11  * furnished to do so, subject to the following conditions:
     12  *
     13  * The above copyright notice and this permission notice shall be included in
     14  * all copies or substantial portions of the Software.
     15  *
     16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
     19  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
     21  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
     22  * THE SOFTWARE.
     23  */
     24 
     25 #include "qemu/osdep.h"
     26 #include "hw/irq.h"
     27 #include "hw/qdev-properties.h"
     28 #include "hw/qdev-properties-system.h"
     29 #include "hw/sparc/grlib.h"
     30 #include "hw/sysbus.h"
     31 #include "qemu/module.h"
     32 #include "chardev/char-fe.h"
     33 
     34 #include "trace.h"
     35 #include "qom/object.h"
     36 
     37 #define UART_REG_SIZE 20     /* Size of memory mapped registers */
     38 
     39 /* UART status register fields */
     40 #define UART_DATA_READY           (1 <<  0)
     41 #define UART_TRANSMIT_SHIFT_EMPTY (1 <<  1)
     42 #define UART_TRANSMIT_FIFO_EMPTY  (1 <<  2)
     43 #define UART_BREAK_RECEIVED       (1 <<  3)
     44 #define UART_OVERRUN              (1 <<  4)
     45 #define UART_PARITY_ERROR         (1 <<  5)
     46 #define UART_FRAMING_ERROR        (1 <<  6)
     47 #define UART_TRANSMIT_FIFO_HALF   (1 <<  7)
     48 #define UART_RECEIVE_FIFO_HALF    (1 <<  8)
     49 #define UART_TRANSMIT_FIFO_FULL   (1 <<  9)
     50 #define UART_RECEIVE_FIFO_FULL    (1 << 10)
     51 
     52 /* UART control register fields */
     53 #define UART_RECEIVE_ENABLE          (1 <<  0)
     54 #define UART_TRANSMIT_ENABLE         (1 <<  1)
     55 #define UART_RECEIVE_INTERRUPT       (1 <<  2)
     56 #define UART_TRANSMIT_INTERRUPT      (1 <<  3)
     57 #define UART_PARITY_SELECT           (1 <<  4)
     58 #define UART_PARITY_ENABLE           (1 <<  5)
     59 #define UART_FLOW_CONTROL            (1 <<  6)
     60 #define UART_LOOPBACK                (1 <<  7)
     61 #define UART_EXTERNAL_CLOCK          (1 <<  8)
     62 #define UART_RECEIVE_FIFO_INTERRUPT  (1 <<  9)
     63 #define UART_TRANSMIT_FIFO_INTERRUPT (1 << 10)
     64 #define UART_FIFO_DEBUG_MODE         (1 << 11)
     65 #define UART_OUTPUT_ENABLE           (1 << 12)
     66 #define UART_FIFO_AVAILABLE          (1 << 31)
     67 
     68 /* Memory mapped register offsets */
     69 #define DATA_OFFSET       0x00
     70 #define STATUS_OFFSET     0x04
     71 #define CONTROL_OFFSET    0x08
     72 #define SCALER_OFFSET     0x0C  /* not supported */
     73 #define FIFO_DEBUG_OFFSET 0x10  /* not supported */
     74 
     75 #define FIFO_LENGTH 1024
     76 
     77 OBJECT_DECLARE_SIMPLE_TYPE(UART, GRLIB_APB_UART)
     78 
     79 struct UART {
     80     SysBusDevice parent_obj;
     81 
     82     MemoryRegion iomem;
     83     qemu_irq irq;
     84 
     85     CharBackend chr;
     86 
     87     /* registers */
     88     uint32_t status;
     89     uint32_t control;
     90 
     91     /* FIFO */
     92     char buffer[FIFO_LENGTH];
     93     int  len;
     94     int  current;
     95 };
     96 
     97 static int uart_data_to_read(UART *uart)
     98 {
     99     return uart->current < uart->len;
    100 }
    101 
    102 static char uart_pop(UART *uart)
    103 {
    104     char ret;
    105 
    106     if (uart->len == 0) {
    107         uart->status &= ~UART_DATA_READY;
    108         return 0;
    109     }
    110 
    111     ret = uart->buffer[uart->current++];
    112 
    113     if (uart->current >= uart->len) {
    114         /* Flush */
    115         uart->len     = 0;
    116         uart->current = 0;
    117     }
    118 
    119     if (!uart_data_to_read(uart)) {
    120         uart->status &= ~UART_DATA_READY;
    121     }
    122 
    123     return ret;
    124 }
    125 
    126 static void uart_add_to_fifo(UART          *uart,
    127                              const uint8_t *buffer,
    128                              int            length)
    129 {
    130     if (uart->len + length > FIFO_LENGTH) {
    131         abort();
    132     }
    133     memcpy(uart->buffer + uart->len, buffer, length);
    134     uart->len += length;
    135 }
    136 
    137 static int grlib_apbuart_can_receive(void *opaque)
    138 {
    139     UART *uart = opaque;
    140 
    141     return FIFO_LENGTH - uart->len;
    142 }
    143 
    144 static void grlib_apbuart_receive(void *opaque, const uint8_t *buf, int size)
    145 {
    146     UART *uart = opaque;
    147 
    148     if (uart->control & UART_RECEIVE_ENABLE) {
    149         uart_add_to_fifo(uart, buf, size);
    150 
    151         uart->status |= UART_DATA_READY;
    152 
    153         if (uart->control & UART_RECEIVE_INTERRUPT) {
    154             qemu_irq_pulse(uart->irq);
    155         }
    156     }
    157 }
    158 
    159 static void grlib_apbuart_event(void *opaque, QEMUChrEvent event)
    160 {
    161     trace_grlib_apbuart_event(event);
    162 }
    163 
    164 
    165 static uint64_t grlib_apbuart_read(void *opaque, hwaddr addr,
    166                                    unsigned size)
    167 {
    168     UART     *uart = opaque;
    169 
    170     addr &= 0xff;
    171 
    172     /* Unit registers */
    173     switch (addr) {
    174     case DATA_OFFSET:
    175     case DATA_OFFSET + 3:       /* when only one byte read */
    176         return uart_pop(uart);
    177 
    178     case STATUS_OFFSET:
    179         /* Read Only */
    180         return uart->status;
    181 
    182     case CONTROL_OFFSET:
    183         return uart->control;
    184 
    185     case SCALER_OFFSET:
    186         /* Not supported */
    187         return 0;
    188 
    189     default:
    190         trace_grlib_apbuart_readl_unknown(addr);
    191         return 0;
    192     }
    193 }
    194 
    195 static void grlib_apbuart_write(void *opaque, hwaddr addr,
    196                                 uint64_t value, unsigned size)
    197 {
    198     UART          *uart = opaque;
    199     unsigned char  c    = 0;
    200 
    201     addr &= 0xff;
    202 
    203     /* Unit registers */
    204     switch (addr) {
    205     case DATA_OFFSET:
    206     case DATA_OFFSET + 3:       /* When only one byte write */
    207         /* Transmit when character device available and transmitter enabled */
    208         if (qemu_chr_fe_backend_connected(&uart->chr) &&
    209             (uart->control & UART_TRANSMIT_ENABLE)) {
    210             c = value & 0xFF;
    211             /* XXX this blocks entire thread. Rewrite to use
    212              * qemu_chr_fe_write and background I/O callbacks */
    213             qemu_chr_fe_write_all(&uart->chr, &c, 1);
    214             /* Generate interrupt */
    215             if (uart->control & UART_TRANSMIT_INTERRUPT) {
    216                 qemu_irq_pulse(uart->irq);
    217             }
    218         }
    219         return;
    220 
    221     case STATUS_OFFSET:
    222         /* Read Only */
    223         return;
    224 
    225     case CONTROL_OFFSET:
    226         uart->control = value;
    227         return;
    228 
    229     case SCALER_OFFSET:
    230         /* Not supported */
    231         return;
    232 
    233     default:
    234         break;
    235     }
    236 
    237     trace_grlib_apbuart_writel_unknown(addr, value);
    238 }
    239 
    240 static const MemoryRegionOps grlib_apbuart_ops = {
    241     .write      = grlib_apbuart_write,
    242     .read       = grlib_apbuart_read,
    243     .endianness = DEVICE_NATIVE_ENDIAN,
    244 };
    245 
    246 static void grlib_apbuart_realize(DeviceState *dev, Error **errp)
    247 {
    248     UART *uart = GRLIB_APB_UART(dev);
    249     SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
    250 
    251     qemu_chr_fe_set_handlers(&uart->chr,
    252                              grlib_apbuart_can_receive,
    253                              grlib_apbuart_receive,
    254                              grlib_apbuart_event,
    255                              NULL, uart, NULL, true);
    256 
    257     sysbus_init_irq(sbd, &uart->irq);
    258 
    259     memory_region_init_io(&uart->iomem, OBJECT(uart), &grlib_apbuart_ops, uart,
    260                           "uart", UART_REG_SIZE);
    261 
    262     sysbus_init_mmio(sbd, &uart->iomem);
    263 }
    264 
    265 static void grlib_apbuart_reset(DeviceState *d)
    266 {
    267     UART *uart = GRLIB_APB_UART(d);
    268 
    269     /* Transmitter FIFO and shift registers are always empty in QEMU */
    270     uart->status =  UART_TRANSMIT_FIFO_EMPTY | UART_TRANSMIT_SHIFT_EMPTY;
    271     /* Everything is off */
    272     uart->control = 0;
    273     /* Flush receive FIFO */
    274     uart->len = 0;
    275     uart->current = 0;
    276 }
    277 
    278 static Property grlib_apbuart_properties[] = {
    279     DEFINE_PROP_CHR("chrdev", UART, chr),
    280     DEFINE_PROP_END_OF_LIST(),
    281 };
    282 
    283 static void grlib_apbuart_class_init(ObjectClass *klass, void *data)
    284 {
    285     DeviceClass *dc = DEVICE_CLASS(klass);
    286 
    287     dc->realize = grlib_apbuart_realize;
    288     dc->reset = grlib_apbuart_reset;
    289     device_class_set_props(dc, grlib_apbuart_properties);
    290 }
    291 
    292 static const TypeInfo grlib_apbuart_info = {
    293     .name          = TYPE_GRLIB_APB_UART,
    294     .parent        = TYPE_SYS_BUS_DEVICE,
    295     .instance_size = sizeof(UART),
    296     .class_init    = grlib_apbuart_class_init,
    297 };
    298 
    299 static void grlib_apbuart_register_types(void)
    300 {
    301     type_register_static(&grlib_apbuart_info);
    302 }
    303 
    304 type_init(grlib_apbuart_register_types)