cachepc-qemu

Fork of AMDESE/qemu with changes for cachepc side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-qemu
Log | Files | Refs | Submodules | LICENSE | sfeed.txt

exynos4210_uart.c (22256B)


      1/*
      2 *  Exynos4210 UART Emulation
      3 *
      4 *  Copyright (C) 2011 Samsung Electronics Co Ltd.
      5 *    Maksim Kozlov, <m.kozlov@samsung.com>
      6 *
      7 *  This program is free software; you can redistribute it and/or modify it
      8 *  under the terms of the GNU General Public License as published by the
      9 *  Free Software Foundation; either version 2 of the License, or
     10 *  (at your option) any later version.
     11 *
     12 *  This program is distributed in the hope that it will be useful, but WITHOUT
     13 *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
     14 *  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
     15 *  for more details.
     16 *
     17 *  You should have received a copy of the GNU General Public License along
     18 *  with this program; if not, see <http://www.gnu.org/licenses/>.
     19 *
     20 */
     21
     22#include "qemu/osdep.h"
     23#include "hw/sysbus.h"
     24#include "migration/vmstate.h"
     25#include "qapi/error.h"
     26#include "qemu/error-report.h"
     27#include "qemu/module.h"
     28#include "qemu/timer.h"
     29#include "chardev/char-fe.h"
     30#include "chardev/char-serial.h"
     31
     32#include "hw/arm/exynos4210.h"
     33#include "hw/irq.h"
     34#include "hw/qdev-properties.h"
     35#include "hw/qdev-properties-system.h"
     36
     37#include "trace.h"
     38#include "qom/object.h"
     39
     40/*
     41 *  Offsets for UART registers relative to SFR base address
     42 *  for UARTn
     43 *
     44 */
     45#define ULCON      0x0000 /* Line Control             */
     46#define UCON       0x0004 /* Control                  */
     47#define UFCON      0x0008 /* FIFO Control             */
     48#define UMCON      0x000C /* Modem Control            */
     49#define UTRSTAT    0x0010 /* Tx/Rx Status             */
     50#define UERSTAT    0x0014 /* UART Error Status        */
     51#define UFSTAT     0x0018 /* FIFO Status              */
     52#define UMSTAT     0x001C /* Modem Status             */
     53#define UTXH       0x0020 /* Transmit Buffer          */
     54#define URXH       0x0024 /* Receive Buffer           */
     55#define UBRDIV     0x0028 /* Baud Rate Divisor        */
     56#define UFRACVAL   0x002C /* Divisor Fractional Value */
     57#define UINTP      0x0030 /* Interrupt Pending        */
     58#define UINTSP     0x0034 /* Interrupt Source Pending */
     59#define UINTM      0x0038 /* Interrupt Mask           */
     60
     61/*
     62 * for indexing register in the uint32_t array
     63 *
     64 * 'reg' - register offset (see offsets definitions above)
     65 *
     66 */
     67#define I_(reg) (reg / sizeof(uint32_t))
     68
     69typedef struct Exynos4210UartReg {
     70    const char         *name; /* the only reason is the debug output */
     71    hwaddr  offset;
     72    uint32_t            reset_value;
     73} Exynos4210UartReg;
     74
     75static const Exynos4210UartReg exynos4210_uart_regs[] = {
     76    {"ULCON",    ULCON,    0x00000000},
     77    {"UCON",     UCON,     0x00003000},
     78    {"UFCON",    UFCON,    0x00000000},
     79    {"UMCON",    UMCON,    0x00000000},
     80    {"UTRSTAT",  UTRSTAT,  0x00000006}, /* RO */
     81    {"UERSTAT",  UERSTAT,  0x00000000}, /* RO */
     82    {"UFSTAT",   UFSTAT,   0x00000000}, /* RO */
     83    {"UMSTAT",   UMSTAT,   0x00000000}, /* RO */
     84    {"UTXH",     UTXH,     0x5c5c5c5c}, /* WO, undefined reset value*/
     85    {"URXH",     URXH,     0x00000000}, /* RO */
     86    {"UBRDIV",   UBRDIV,   0x00000000},
     87    {"UFRACVAL", UFRACVAL, 0x00000000},
     88    {"UINTP",    UINTP,    0x00000000},
     89    {"UINTSP",   UINTSP,   0x00000000},
     90    {"UINTM",    UINTM,    0x00000000},
     91};
     92
     93#define EXYNOS4210_UART_REGS_MEM_SIZE    0x3C
     94
     95/* UART FIFO Control */
     96#define UFCON_FIFO_ENABLE                    0x1
     97#define UFCON_Rx_FIFO_RESET                  0x2
     98#define UFCON_Tx_FIFO_RESET                  0x4
     99#define UFCON_Tx_FIFO_TRIGGER_LEVEL_SHIFT    8
    100#define UFCON_Tx_FIFO_TRIGGER_LEVEL (7 << UFCON_Tx_FIFO_TRIGGER_LEVEL_SHIFT)
    101#define UFCON_Rx_FIFO_TRIGGER_LEVEL_SHIFT    4
    102#define UFCON_Rx_FIFO_TRIGGER_LEVEL (7 << UFCON_Rx_FIFO_TRIGGER_LEVEL_SHIFT)
    103
    104/* Uart FIFO Status */
    105#define UFSTAT_Rx_FIFO_COUNT        0xff
    106#define UFSTAT_Rx_FIFO_FULL         0x100
    107#define UFSTAT_Rx_FIFO_ERROR        0x200
    108#define UFSTAT_Tx_FIFO_COUNT_SHIFT  16
    109#define UFSTAT_Tx_FIFO_COUNT        (0xff << UFSTAT_Tx_FIFO_COUNT_SHIFT)
    110#define UFSTAT_Tx_FIFO_FULL_SHIFT   24
    111#define UFSTAT_Tx_FIFO_FULL         (1 << UFSTAT_Tx_FIFO_FULL_SHIFT)
    112
    113/* UART Interrupt Source Pending */
    114#define UINTSP_RXD      0x1 /* Receive interrupt  */
    115#define UINTSP_ERROR    0x2 /* Error interrupt    */
    116#define UINTSP_TXD      0x4 /* Transmit interrupt */
    117#define UINTSP_MODEM    0x8 /* Modem interrupt    */
    118
    119/* UART Line Control */
    120#define ULCON_IR_MODE_SHIFT   6
    121#define ULCON_PARITY_SHIFT    3
    122#define ULCON_STOP_BIT_SHIFT  1
    123
    124/* UART Tx/Rx Status */
    125#define UTRSTAT_Rx_TIMEOUT              0x8
    126#define UTRSTAT_TRANSMITTER_EMPTY       0x4
    127#define UTRSTAT_Tx_BUFFER_EMPTY         0x2
    128#define UTRSTAT_Rx_BUFFER_DATA_READY    0x1
    129
    130/* UART Error Status */
    131#define UERSTAT_OVERRUN  0x1
    132#define UERSTAT_PARITY   0x2
    133#define UERSTAT_FRAME    0x4
    134#define UERSTAT_BREAK    0x8
    135
    136typedef struct {
    137    uint8_t    *data;
    138    uint32_t    sp, rp; /* store and retrieve pointers */
    139    uint32_t    size;
    140} Exynos4210UartFIFO;
    141
    142#define TYPE_EXYNOS4210_UART "exynos4210.uart"
    143OBJECT_DECLARE_SIMPLE_TYPE(Exynos4210UartState, EXYNOS4210_UART)
    144
    145struct Exynos4210UartState {
    146    SysBusDevice parent_obj;
    147
    148    MemoryRegion iomem;
    149
    150    uint32_t             reg[EXYNOS4210_UART_REGS_MEM_SIZE / sizeof(uint32_t)];
    151    Exynos4210UartFIFO   rx;
    152    Exynos4210UartFIFO   tx;
    153
    154    QEMUTimer *fifo_timeout_timer;
    155    uint64_t wordtime;        /* word time in ns */
    156
    157    CharBackend       chr;
    158    qemu_irq          irq;
    159    qemu_irq          dmairq;
    160
    161    uint32_t channel;
    162
    163};
    164
    165
    166/* Used only for tracing */
    167static const char *exynos4210_uart_regname(hwaddr  offset)
    168{
    169
    170    int i;
    171
    172    for (i = 0; i < ARRAY_SIZE(exynos4210_uart_regs); i++) {
    173        if (offset == exynos4210_uart_regs[i].offset) {
    174            return exynos4210_uart_regs[i].name;
    175        }
    176    }
    177
    178    return NULL;
    179}
    180
    181
    182static void fifo_store(Exynos4210UartFIFO *q, uint8_t ch)
    183{
    184    q->data[q->sp] = ch;
    185    q->sp = (q->sp + 1) % q->size;
    186}
    187
    188static uint8_t fifo_retrieve(Exynos4210UartFIFO *q)
    189{
    190    uint8_t ret = q->data[q->rp];
    191    q->rp = (q->rp + 1) % q->size;
    192    return  ret;
    193}
    194
    195static int fifo_elements_number(const Exynos4210UartFIFO *q)
    196{
    197    if (q->sp < q->rp) {
    198        return q->size - q->rp + q->sp;
    199    }
    200
    201    return q->sp - q->rp;
    202}
    203
    204static int fifo_empty_elements_number(const Exynos4210UartFIFO *q)
    205{
    206    return q->size - fifo_elements_number(q);
    207}
    208
    209static void fifo_reset(Exynos4210UartFIFO *q)
    210{
    211    g_free(q->data);
    212    q->data = NULL;
    213
    214    q->data = (uint8_t *)g_malloc0(q->size);
    215
    216    q->sp = 0;
    217    q->rp = 0;
    218}
    219
    220static uint32_t exynos4210_uart_FIFO_trigger_level(uint32_t channel,
    221                                                   uint32_t reg)
    222{
    223    uint32_t level;
    224
    225    switch (channel) {
    226    case 0:
    227        level = reg * 32;
    228        break;
    229    case 1:
    230    case 4:
    231        level = reg * 8;
    232        break;
    233    case 2:
    234    case 3:
    235        level = reg * 2;
    236        break;
    237    default:
    238        level = 0;
    239        trace_exynos_uart_channel_error(channel);
    240        break;
    241    }
    242    return level;
    243}
    244
    245static uint32_t
    246exynos4210_uart_Tx_FIFO_trigger_level(const Exynos4210UartState *s)
    247{
    248    uint32_t reg;
    249
    250    reg = (s->reg[I_(UFCON)] & UFCON_Tx_FIFO_TRIGGER_LEVEL) >>
    251            UFCON_Tx_FIFO_TRIGGER_LEVEL_SHIFT;
    252
    253    return exynos4210_uart_FIFO_trigger_level(s->channel, reg);
    254}
    255
    256static uint32_t
    257exynos4210_uart_Rx_FIFO_trigger_level(const Exynos4210UartState *s)
    258{
    259    uint32_t reg;
    260
    261    reg = ((s->reg[I_(UFCON)] & UFCON_Rx_FIFO_TRIGGER_LEVEL) >>
    262            UFCON_Rx_FIFO_TRIGGER_LEVEL_SHIFT) + 1;
    263
    264    return exynos4210_uart_FIFO_trigger_level(s->channel, reg);
    265}
    266
    267/*
    268 * Update Rx DMA busy signal if Rx DMA is enabled. For simplicity,
    269 * mark DMA as busy if DMA is enabled and the receive buffer is empty.
    270 */
    271static void exynos4210_uart_update_dmabusy(Exynos4210UartState *s)
    272{
    273    bool rx_dma_enabled = (s->reg[I_(UCON)] & 0x03) == 0x02;
    274    uint32_t count = fifo_elements_number(&s->rx);
    275
    276    if (rx_dma_enabled && !count) {
    277        qemu_irq_raise(s->dmairq);
    278        trace_exynos_uart_dmabusy(s->channel);
    279    } else {
    280        qemu_irq_lower(s->dmairq);
    281        trace_exynos_uart_dmaready(s->channel);
    282    }
    283}
    284
    285static void exynos4210_uart_update_irq(Exynos4210UartState *s)
    286{
    287    /*
    288     * The Tx interrupt is always requested if the number of data in the
    289     * transmit FIFO is smaller than the trigger level.
    290     */
    291    if (s->reg[I_(UFCON)] & UFCON_FIFO_ENABLE) {
    292        uint32_t count = (s->reg[I_(UFSTAT)] & UFSTAT_Tx_FIFO_COUNT) >>
    293                UFSTAT_Tx_FIFO_COUNT_SHIFT;
    294
    295        if (count <= exynos4210_uart_Tx_FIFO_trigger_level(s)) {
    296            s->reg[I_(UINTSP)] |= UINTSP_TXD;
    297        }
    298
    299        /*
    300         * Rx interrupt if trigger level is reached or if rx timeout
    301         * interrupt is disabled and there is data in the receive buffer
    302         */
    303        count = fifo_elements_number(&s->rx);
    304        if ((count && !(s->reg[I_(UCON)] & 0x80)) ||
    305            count >= exynos4210_uart_Rx_FIFO_trigger_level(s)) {
    306            exynos4210_uart_update_dmabusy(s);
    307            s->reg[I_(UINTSP)] |= UINTSP_RXD;
    308            timer_del(s->fifo_timeout_timer);
    309        }
    310    } else if (s->reg[I_(UTRSTAT)] & UTRSTAT_Rx_BUFFER_DATA_READY) {
    311        exynos4210_uart_update_dmabusy(s);
    312        s->reg[I_(UINTSP)] |= UINTSP_RXD;
    313    }
    314
    315    s->reg[I_(UINTP)] = s->reg[I_(UINTSP)] & ~s->reg[I_(UINTM)];
    316
    317    if (s->reg[I_(UINTP)]) {
    318        qemu_irq_raise(s->irq);
    319        trace_exynos_uart_irq_raised(s->channel, s->reg[I_(UINTP)]);
    320    } else {
    321        qemu_irq_lower(s->irq);
    322        trace_exynos_uart_irq_lowered(s->channel);
    323    }
    324}
    325
    326static void exynos4210_uart_timeout_int(void *opaque)
    327{
    328    Exynos4210UartState *s = opaque;
    329
    330    trace_exynos_uart_rx_timeout(s->channel, s->reg[I_(UTRSTAT)],
    331                                 s->reg[I_(UINTSP)]);
    332
    333    if ((s->reg[I_(UTRSTAT)] & UTRSTAT_Rx_BUFFER_DATA_READY) ||
    334        (s->reg[I_(UCON)] & (1 << 11))) {
    335        s->reg[I_(UINTSP)] |= UINTSP_RXD;
    336        s->reg[I_(UTRSTAT)] |= UTRSTAT_Rx_TIMEOUT;
    337        exynos4210_uart_update_dmabusy(s);
    338        exynos4210_uart_update_irq(s);
    339    }
    340}
    341
    342static void exynos4210_uart_update_parameters(Exynos4210UartState *s)
    343{
    344    int speed, parity, data_bits, stop_bits;
    345    QEMUSerialSetParams ssp;
    346    uint64_t uclk_rate;
    347
    348    if (s->reg[I_(UBRDIV)] == 0) {
    349        return;
    350    }
    351
    352    if (s->reg[I_(ULCON)] & 0x20) {
    353        if (s->reg[I_(ULCON)] & 0x28) {
    354            parity = 'E';
    355        } else {
    356            parity = 'O';
    357        }
    358    } else {
    359        parity = 'N';
    360    }
    361
    362    if (s->reg[I_(ULCON)] & 0x4) {
    363        stop_bits = 2;
    364    } else {
    365        stop_bits = 1;
    366    }
    367
    368    data_bits = (s->reg[I_(ULCON)] & 0x3) + 5;
    369
    370    uclk_rate = 24000000;
    371
    372    speed = uclk_rate / ((16 * (s->reg[I_(UBRDIV)]) & 0xffff) +
    373            (s->reg[I_(UFRACVAL)] & 0x7) + 16);
    374
    375    ssp.speed     = speed;
    376    ssp.parity    = parity;
    377    ssp.data_bits = data_bits;
    378    ssp.stop_bits = stop_bits;
    379
    380    s->wordtime = NANOSECONDS_PER_SECOND * (data_bits + stop_bits + 1) / speed;
    381
    382    qemu_chr_fe_ioctl(&s->chr, CHR_IOCTL_SERIAL_SET_PARAMS, &ssp);
    383
    384    trace_exynos_uart_update_params(
    385                s->channel, speed, parity, data_bits, stop_bits, s->wordtime);
    386}
    387
    388static void exynos4210_uart_rx_timeout_set(Exynos4210UartState *s)
    389{
    390    if (s->reg[I_(UCON)] & 0x80) {
    391        uint32_t timeout = ((s->reg[I_(UCON)] >> 12) & 0x0f) * s->wordtime;
    392
    393        timer_mod(s->fifo_timeout_timer,
    394                  qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + timeout);
    395    } else {
    396        timer_del(s->fifo_timeout_timer);
    397    }
    398}
    399
    400static void exynos4210_uart_write(void *opaque, hwaddr offset,
    401                               uint64_t val, unsigned size)
    402{
    403    Exynos4210UartState *s = (Exynos4210UartState *)opaque;
    404    uint8_t ch;
    405
    406    trace_exynos_uart_write(s->channel, offset,
    407                            exynos4210_uart_regname(offset), val);
    408
    409    switch (offset) {
    410    case ULCON:
    411    case UBRDIV:
    412    case UFRACVAL:
    413        s->reg[I_(offset)] = val;
    414        exynos4210_uart_update_parameters(s);
    415        break;
    416    case UFCON:
    417        s->reg[I_(UFCON)] = val;
    418        if (val & UFCON_Rx_FIFO_RESET) {
    419            fifo_reset(&s->rx);
    420            s->reg[I_(UFCON)] &= ~UFCON_Rx_FIFO_RESET;
    421            trace_exynos_uart_rx_fifo_reset(s->channel);
    422        }
    423        if (val & UFCON_Tx_FIFO_RESET) {
    424            fifo_reset(&s->tx);
    425            s->reg[I_(UFCON)] &= ~UFCON_Tx_FIFO_RESET;
    426            trace_exynos_uart_tx_fifo_reset(s->channel);
    427        }
    428        break;
    429
    430    case UTXH:
    431        if (qemu_chr_fe_backend_connected(&s->chr)) {
    432            s->reg[I_(UTRSTAT)] &= ~(UTRSTAT_TRANSMITTER_EMPTY |
    433                    UTRSTAT_Tx_BUFFER_EMPTY);
    434            ch = (uint8_t)val;
    435            /* XXX this blocks entire thread. Rewrite to use
    436             * qemu_chr_fe_write and background I/O callbacks */
    437            qemu_chr_fe_write_all(&s->chr, &ch, 1);
    438            trace_exynos_uart_tx(s->channel, ch);
    439            s->reg[I_(UTRSTAT)] |= UTRSTAT_TRANSMITTER_EMPTY |
    440                    UTRSTAT_Tx_BUFFER_EMPTY;
    441            s->reg[I_(UINTSP)]  |= UINTSP_TXD;
    442            exynos4210_uart_update_irq(s);
    443        }
    444        break;
    445
    446    case UINTP:
    447        s->reg[I_(UINTP)] &= ~val;
    448        s->reg[I_(UINTSP)] &= ~val;
    449        trace_exynos_uart_intclr(s->channel, s->reg[I_(UINTP)]);
    450        exynos4210_uart_update_irq(s);
    451        break;
    452    case UTRSTAT:
    453        if (val & UTRSTAT_Rx_TIMEOUT) {
    454            s->reg[I_(UTRSTAT)] &= ~UTRSTAT_Rx_TIMEOUT;
    455        }
    456        break;
    457    case UERSTAT:
    458    case UFSTAT:
    459    case UMSTAT:
    460    case URXH:
    461        trace_exynos_uart_ro_write(
    462                    s->channel, exynos4210_uart_regname(offset), offset);
    463        break;
    464    case UINTSP:
    465        s->reg[I_(UINTSP)]  &= ~val;
    466        break;
    467    case UINTM:
    468        s->reg[I_(UINTM)] = val;
    469        exynos4210_uart_update_irq(s);
    470        break;
    471    case UCON:
    472    case UMCON:
    473    default:
    474        s->reg[I_(offset)] = val;
    475        break;
    476    }
    477}
    478
    479static uint64_t exynos4210_uart_read(void *opaque, hwaddr offset,
    480                                  unsigned size)
    481{
    482    Exynos4210UartState *s = (Exynos4210UartState *)opaque;
    483    uint32_t res;
    484
    485    switch (offset) {
    486    case UERSTAT: /* Read Only */
    487        res = s->reg[I_(UERSTAT)];
    488        s->reg[I_(UERSTAT)] = 0;
    489        trace_exynos_uart_read(s->channel, offset,
    490                               exynos4210_uart_regname(offset), res);
    491        return res;
    492    case UFSTAT: /* Read Only */
    493        s->reg[I_(UFSTAT)] = fifo_elements_number(&s->rx) & 0xff;
    494        if (fifo_empty_elements_number(&s->rx) == 0) {
    495            s->reg[I_(UFSTAT)] |= UFSTAT_Rx_FIFO_FULL;
    496            s->reg[I_(UFSTAT)] &= ~0xff;
    497        }
    498        trace_exynos_uart_read(s->channel, offset,
    499                               exynos4210_uart_regname(offset),
    500                               s->reg[I_(UFSTAT)]);
    501        return s->reg[I_(UFSTAT)];
    502    case URXH:
    503        if (s->reg[I_(UFCON)] & UFCON_FIFO_ENABLE) {
    504            if (fifo_elements_number(&s->rx)) {
    505                res = fifo_retrieve(&s->rx);
    506                trace_exynos_uart_rx(s->channel, res);
    507                if (!fifo_elements_number(&s->rx)) {
    508                    s->reg[I_(UTRSTAT)] &= ~UTRSTAT_Rx_BUFFER_DATA_READY;
    509                } else {
    510                    s->reg[I_(UTRSTAT)] |= UTRSTAT_Rx_BUFFER_DATA_READY;
    511                }
    512            } else {
    513                trace_exynos_uart_rx_error(s->channel);
    514                s->reg[I_(UINTSP)] |= UINTSP_ERROR;
    515                exynos4210_uart_update_irq(s);
    516                res = 0;
    517            }
    518        } else {
    519            s->reg[I_(UTRSTAT)] &= ~UTRSTAT_Rx_BUFFER_DATA_READY;
    520            res = s->reg[I_(URXH)];
    521        }
    522        qemu_chr_fe_accept_input(&s->chr);
    523        exynos4210_uart_update_dmabusy(s);
    524        trace_exynos_uart_read(s->channel, offset,
    525                               exynos4210_uart_regname(offset), res);
    526        return res;
    527    case UTXH:
    528        trace_exynos_uart_wo_read(s->channel, exynos4210_uart_regname(offset),
    529                                  offset);
    530        break;
    531    default:
    532        trace_exynos_uart_read(s->channel, offset,
    533                               exynos4210_uart_regname(offset),
    534                               s->reg[I_(offset)]);
    535        return s->reg[I_(offset)];
    536    }
    537
    538    trace_exynos_uart_read(s->channel, offset, exynos4210_uart_regname(offset),
    539                           0);
    540    return 0;
    541}
    542
    543static const MemoryRegionOps exynos4210_uart_ops = {
    544    .read = exynos4210_uart_read,
    545    .write = exynos4210_uart_write,
    546    .endianness = DEVICE_NATIVE_ENDIAN,
    547    .valid = {
    548        .max_access_size = 4,
    549        .unaligned = false
    550    },
    551};
    552
    553static int exynos4210_uart_can_receive(void *opaque)
    554{
    555    Exynos4210UartState *s = (Exynos4210UartState *)opaque;
    556
    557    if (s->reg[I_(UFCON)] & UFCON_FIFO_ENABLE) {
    558        return fifo_empty_elements_number(&s->rx);
    559    } else {
    560        return !(s->reg[I_(UTRSTAT)] & UTRSTAT_Rx_BUFFER_DATA_READY);
    561    }
    562}
    563
    564static void exynos4210_uart_receive(void *opaque, const uint8_t *buf, int size)
    565{
    566    Exynos4210UartState *s = (Exynos4210UartState *)opaque;
    567    int i;
    568
    569    if (s->reg[I_(UFCON)] & UFCON_FIFO_ENABLE) {
    570        if (fifo_empty_elements_number(&s->rx) < size) {
    571            size = fifo_empty_elements_number(&s->rx);
    572            s->reg[I_(UINTSP)] |= UINTSP_ERROR;
    573        }
    574        for (i = 0; i < size; i++) {
    575            fifo_store(&s->rx, buf[i]);
    576        }
    577        exynos4210_uart_rx_timeout_set(s);
    578    } else {
    579        s->reg[I_(URXH)] = buf[0];
    580    }
    581    s->reg[I_(UTRSTAT)] |= UTRSTAT_Rx_BUFFER_DATA_READY;
    582
    583    exynos4210_uart_update_irq(s);
    584}
    585
    586
    587static void exynos4210_uart_event(void *opaque, QEMUChrEvent event)
    588{
    589    Exynos4210UartState *s = (Exynos4210UartState *)opaque;
    590
    591    if (event == CHR_EVENT_BREAK) {
    592        /* When the RxDn is held in logic 0, then a null byte is pushed into the
    593         * fifo */
    594        fifo_store(&s->rx, '\0');
    595        s->reg[I_(UERSTAT)] |= UERSTAT_BREAK;
    596        exynos4210_uart_update_irq(s);
    597    }
    598}
    599
    600
    601static void exynos4210_uart_reset(DeviceState *dev)
    602{
    603    Exynos4210UartState *s = EXYNOS4210_UART(dev);
    604    int i;
    605
    606    for (i = 0; i < ARRAY_SIZE(exynos4210_uart_regs); i++) {
    607        s->reg[I_(exynos4210_uart_regs[i].offset)] =
    608                exynos4210_uart_regs[i].reset_value;
    609    }
    610
    611    fifo_reset(&s->rx);
    612    fifo_reset(&s->tx);
    613
    614    trace_exynos_uart_rxsize(s->channel, s->rx.size);
    615}
    616
    617static int exynos4210_uart_post_load(void *opaque, int version_id)
    618{
    619    Exynos4210UartState *s = (Exynos4210UartState *)opaque;
    620
    621    exynos4210_uart_update_parameters(s);
    622    exynos4210_uart_rx_timeout_set(s);
    623
    624    return 0;
    625}
    626
    627static const VMStateDescription vmstate_exynos4210_uart_fifo = {
    628    .name = "exynos4210.uart.fifo",
    629    .version_id = 1,
    630    .minimum_version_id = 1,
    631    .post_load = exynos4210_uart_post_load,
    632    .fields = (VMStateField[]) {
    633        VMSTATE_UINT32(sp, Exynos4210UartFIFO),
    634        VMSTATE_UINT32(rp, Exynos4210UartFIFO),
    635        VMSTATE_VBUFFER_UINT32(data, Exynos4210UartFIFO, 1, NULL, size),
    636        VMSTATE_END_OF_LIST()
    637    }
    638};
    639
    640static const VMStateDescription vmstate_exynos4210_uart = {
    641    .name = "exynos4210.uart",
    642    .version_id = 1,
    643    .minimum_version_id = 1,
    644    .fields = (VMStateField[]) {
    645        VMSTATE_STRUCT(rx, Exynos4210UartState, 1,
    646                       vmstate_exynos4210_uart_fifo, Exynos4210UartFIFO),
    647        VMSTATE_UINT32_ARRAY(reg, Exynos4210UartState,
    648                             EXYNOS4210_UART_REGS_MEM_SIZE / sizeof(uint32_t)),
    649        VMSTATE_END_OF_LIST()
    650    }
    651};
    652
    653DeviceState *exynos4210_uart_create(hwaddr addr,
    654                                    int fifo_size,
    655                                    int channel,
    656                                    Chardev *chr,
    657                                    qemu_irq irq)
    658{
    659    DeviceState  *dev;
    660    SysBusDevice *bus;
    661
    662    dev = qdev_new(TYPE_EXYNOS4210_UART);
    663
    664    qdev_prop_set_chr(dev, "chardev", chr);
    665    qdev_prop_set_uint32(dev, "channel", channel);
    666    qdev_prop_set_uint32(dev, "rx-size", fifo_size);
    667    qdev_prop_set_uint32(dev, "tx-size", fifo_size);
    668
    669    bus = SYS_BUS_DEVICE(dev);
    670    sysbus_realize_and_unref(bus, &error_fatal);
    671    if (addr != (hwaddr)-1) {
    672        sysbus_mmio_map(bus, 0, addr);
    673    }
    674    sysbus_connect_irq(bus, 0, irq);
    675
    676    return dev;
    677}
    678
    679static void exynos4210_uart_init(Object *obj)
    680{
    681    SysBusDevice *dev = SYS_BUS_DEVICE(obj);
    682    Exynos4210UartState *s = EXYNOS4210_UART(dev);
    683
    684    s->wordtime = NANOSECONDS_PER_SECOND * 10 / 9600;
    685
    686    /* memory mapping */
    687    memory_region_init_io(&s->iomem, obj, &exynos4210_uart_ops, s,
    688                          "exynos4210.uart", EXYNOS4210_UART_REGS_MEM_SIZE);
    689    sysbus_init_mmio(dev, &s->iomem);
    690
    691    sysbus_init_irq(dev, &s->irq);
    692    sysbus_init_irq(dev, &s->dmairq);
    693}
    694
    695static void exynos4210_uart_realize(DeviceState *dev, Error **errp)
    696{
    697    Exynos4210UartState *s = EXYNOS4210_UART(dev);
    698
    699    s->fifo_timeout_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL,
    700                                         exynos4210_uart_timeout_int, s);
    701
    702    qemu_chr_fe_set_handlers(&s->chr, exynos4210_uart_can_receive,
    703                             exynos4210_uart_receive, exynos4210_uart_event,
    704                             NULL, s, NULL, true);
    705}
    706
    707static Property exynos4210_uart_properties[] = {
    708    DEFINE_PROP_CHR("chardev", Exynos4210UartState, chr),
    709    DEFINE_PROP_UINT32("channel", Exynos4210UartState, channel, 0),
    710    DEFINE_PROP_UINT32("rx-size", Exynos4210UartState, rx.size, 16),
    711    DEFINE_PROP_UINT32("tx-size", Exynos4210UartState, tx.size, 16),
    712    DEFINE_PROP_END_OF_LIST(),
    713};
    714
    715static void exynos4210_uart_class_init(ObjectClass *klass, void *data)
    716{
    717    DeviceClass *dc = DEVICE_CLASS(klass);
    718
    719    dc->realize = exynos4210_uart_realize;
    720    dc->reset = exynos4210_uart_reset;
    721    device_class_set_props(dc, exynos4210_uart_properties);
    722    dc->vmsd = &vmstate_exynos4210_uart;
    723}
    724
    725static const TypeInfo exynos4210_uart_info = {
    726    .name          = TYPE_EXYNOS4210_UART,
    727    .parent        = TYPE_SYS_BUS_DEVICE,
    728    .instance_size = sizeof(Exynos4210UartState),
    729    .instance_init = exynos4210_uart_init,
    730    .class_init    = exynos4210_uart_class_init,
    731};
    732
    733static void exynos4210_uart_register(void)
    734{
    735    type_register_static(&exynos4210_uart_info);
    736}
    737
    738type_init(exynos4210_uart_register)