qemu/hw/char/lm32_uart.c
<<
>>
Prefs
   1/*
   2 *  QEMU model of the LatticeMico32 UART block.
   3 *
   4 *  Copyright (c) 2010 Michael Walle <michael@walle.cc>
   5 *
   6 * This library is free software; you can redistribute it and/or
   7 * modify it under the terms of the GNU Lesser General Public
   8 * License as published by the Free Software Foundation; either
   9 * version 2 of the License, or (at your option) any later version.
  10 *
  11 * This library is distributed in the hope that it will be useful,
  12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  14 * Lesser General Public License for more details.
  15 *
  16 * You should have received a copy of the GNU Lesser General Public
  17 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
  18 *
  19 *
  20 * Specification available at:
  21 *   http://www.latticesemi.com/documents/mico32uart.pdf
  22 */
  23
  24
  25#include "qemu/osdep.h"
  26#include "hw/irq.h"
  27#include "hw/qdev-properties.h"
  28#include "hw/sysbus.h"
  29#include "migration/vmstate.h"
  30#include "trace.h"
  31#include "chardev/char-fe.h"
  32#include "qemu/error-report.h"
  33#include "qemu/module.h"
  34
  35enum {
  36    R_RXTX = 0,
  37    R_IER,
  38    R_IIR,
  39    R_LCR,
  40    R_MCR,
  41    R_LSR,
  42    R_MSR,
  43    R_DIV,
  44    R_MAX
  45};
  46
  47enum {
  48    IER_RBRI = (1<<0),
  49    IER_THRI = (1<<1),
  50    IER_RLSI = (1<<2),
  51    IER_MSI  = (1<<3),
  52};
  53
  54enum {
  55    IIR_STAT = (1<<0),
  56    IIR_ID0  = (1<<1),
  57    IIR_ID1  = (1<<2),
  58};
  59
  60enum {
  61    LCR_WLS0 = (1<<0),
  62    LCR_WLS1 = (1<<1),
  63    LCR_STB  = (1<<2),
  64    LCR_PEN  = (1<<3),
  65    LCR_EPS  = (1<<4),
  66    LCR_SP   = (1<<5),
  67    LCR_SB   = (1<<6),
  68};
  69
  70enum {
  71    MCR_DTR  = (1<<0),
  72    MCR_RTS  = (1<<1),
  73};
  74
  75enum {
  76    LSR_DR   = (1<<0),
  77    LSR_OE   = (1<<1),
  78    LSR_PE   = (1<<2),
  79    LSR_FE   = (1<<3),
  80    LSR_BI   = (1<<4),
  81    LSR_THRE = (1<<5),
  82    LSR_TEMT = (1<<6),
  83};
  84
  85enum {
  86    MSR_DCTS = (1<<0),
  87    MSR_DDSR = (1<<1),
  88    MSR_TERI = (1<<2),
  89    MSR_DDCD = (1<<3),
  90    MSR_CTS  = (1<<4),
  91    MSR_DSR  = (1<<5),
  92    MSR_RI   = (1<<6),
  93    MSR_DCD  = (1<<7),
  94};
  95
  96#define TYPE_LM32_UART "lm32-uart"
  97#define LM32_UART(obj) OBJECT_CHECK(LM32UartState, (obj), TYPE_LM32_UART)
  98
  99struct LM32UartState {
 100    SysBusDevice parent_obj;
 101
 102    MemoryRegion iomem;
 103    CharBackend chr;
 104    qemu_irq irq;
 105
 106    uint32_t regs[R_MAX];
 107};
 108typedef struct LM32UartState LM32UartState;
 109
 110static void uart_update_irq(LM32UartState *s)
 111{
 112    unsigned int irq;
 113
 114    if ((s->regs[R_LSR] & (LSR_OE | LSR_PE | LSR_FE | LSR_BI))
 115            && (s->regs[R_IER] & IER_RLSI)) {
 116        irq = 1;
 117        s->regs[R_IIR] = IIR_ID1 | IIR_ID0;
 118    } else if ((s->regs[R_LSR] & LSR_DR) && (s->regs[R_IER] & IER_RBRI)) {
 119        irq = 1;
 120        s->regs[R_IIR] = IIR_ID1;
 121    } else if ((s->regs[R_LSR] & LSR_THRE) && (s->regs[R_IER] & IER_THRI)) {
 122        irq = 1;
 123        s->regs[R_IIR] = IIR_ID0;
 124    } else if ((s->regs[R_MSR] & 0x0f) && (s->regs[R_IER] & IER_MSI)) {
 125        irq = 1;
 126        s->regs[R_IIR] = 0;
 127    } else {
 128        irq = 0;
 129        s->regs[R_IIR] = IIR_STAT;
 130    }
 131
 132    trace_lm32_uart_irq_state(irq);
 133    qemu_set_irq(s->irq, irq);
 134}
 135
 136static uint64_t uart_read(void *opaque, hwaddr addr,
 137                          unsigned size)
 138{
 139    LM32UartState *s = opaque;
 140    uint32_t r = 0;
 141
 142    addr >>= 2;
 143    switch (addr) {
 144    case R_RXTX:
 145        r = s->regs[R_RXTX];
 146        s->regs[R_LSR] &= ~LSR_DR;
 147        uart_update_irq(s);
 148        qemu_chr_fe_accept_input(&s->chr);
 149        break;
 150    case R_IIR:
 151    case R_LSR:
 152    case R_MSR:
 153        r = s->regs[addr];
 154        break;
 155    case R_IER:
 156    case R_LCR:
 157    case R_MCR:
 158    case R_DIV:
 159        error_report("lm32_uart: read access to write only register 0x"
 160                TARGET_FMT_plx, addr << 2);
 161        break;
 162    default:
 163        error_report("lm32_uart: read access to unknown register 0x"
 164                TARGET_FMT_plx, addr << 2);
 165        break;
 166    }
 167
 168    trace_lm32_uart_memory_read(addr << 2, r);
 169    return r;
 170}
 171
 172static void uart_write(void *opaque, hwaddr addr,
 173                       uint64_t value, unsigned size)
 174{
 175    LM32UartState *s = opaque;
 176    unsigned char ch = value;
 177
 178    trace_lm32_uart_memory_write(addr, value);
 179
 180    addr >>= 2;
 181    switch (addr) {
 182    case R_RXTX:
 183        /* XXX this blocks entire thread. Rewrite to use
 184         * qemu_chr_fe_write and background I/O callbacks */
 185        qemu_chr_fe_write_all(&s->chr, &ch, 1);
 186        break;
 187    case R_IER:
 188    case R_LCR:
 189    case R_MCR:
 190    case R_DIV:
 191        s->regs[addr] = value;
 192        break;
 193    case R_IIR:
 194    case R_LSR:
 195    case R_MSR:
 196        error_report("lm32_uart: write access to read only register 0x"
 197                TARGET_FMT_plx, addr << 2);
 198        break;
 199    default:
 200        error_report("lm32_uart: write access to unknown register 0x"
 201                TARGET_FMT_plx, addr << 2);
 202        break;
 203    }
 204    uart_update_irq(s);
 205}
 206
 207static const MemoryRegionOps uart_ops = {
 208    .read = uart_read,
 209    .write = uart_write,
 210    .endianness = DEVICE_NATIVE_ENDIAN,
 211    .valid = {
 212        .min_access_size = 4,
 213        .max_access_size = 4,
 214    },
 215};
 216
 217static void uart_rx(void *opaque, const uint8_t *buf, int size)
 218{
 219    LM32UartState *s = opaque;
 220
 221    if (s->regs[R_LSR] & LSR_DR) {
 222        s->regs[R_LSR] |= LSR_OE;
 223    }
 224
 225    s->regs[R_LSR] |= LSR_DR;
 226    s->regs[R_RXTX] = *buf;
 227
 228    uart_update_irq(s);
 229}
 230
 231static int uart_can_rx(void *opaque)
 232{
 233    LM32UartState *s = opaque;
 234
 235    return !(s->regs[R_LSR] & LSR_DR);
 236}
 237
 238static void uart_event(void *opaque, int event)
 239{
 240}
 241
 242static void uart_reset(DeviceState *d)
 243{
 244    LM32UartState *s = LM32_UART(d);
 245    int i;
 246
 247    for (i = 0; i < R_MAX; i++) {
 248        s->regs[i] = 0;
 249    }
 250
 251    /* defaults */
 252    s->regs[R_LSR] = LSR_THRE | LSR_TEMT;
 253}
 254
 255static void lm32_uart_init(Object *obj)
 256{
 257    LM32UartState *s = LM32_UART(obj);
 258    SysBusDevice *dev = SYS_BUS_DEVICE(obj);
 259
 260    sysbus_init_irq(dev, &s->irq);
 261
 262    memory_region_init_io(&s->iomem, obj, &uart_ops, s,
 263                          "uart", R_MAX * 4);
 264    sysbus_init_mmio(dev, &s->iomem);
 265}
 266
 267static void lm32_uart_realize(DeviceState *dev, Error **errp)
 268{
 269    LM32UartState *s = LM32_UART(dev);
 270
 271    qemu_chr_fe_set_handlers(&s->chr, uart_can_rx, uart_rx,
 272                             uart_event, NULL, s, NULL, true);
 273}
 274
 275static const VMStateDescription vmstate_lm32_uart = {
 276    .name = "lm32-uart",
 277    .version_id = 1,
 278    .minimum_version_id = 1,
 279    .fields = (VMStateField[]) {
 280        VMSTATE_UINT32_ARRAY(regs, LM32UartState, R_MAX),
 281        VMSTATE_END_OF_LIST()
 282    }
 283};
 284
 285static Property lm32_uart_properties[] = {
 286    DEFINE_PROP_CHR("chardev", LM32UartState, chr),
 287    DEFINE_PROP_END_OF_LIST(),
 288};
 289
 290static void lm32_uart_class_init(ObjectClass *klass, void *data)
 291{
 292    DeviceClass *dc = DEVICE_CLASS(klass);
 293
 294    dc->reset = uart_reset;
 295    dc->vmsd = &vmstate_lm32_uart;
 296    dc->props = lm32_uart_properties;
 297    dc->realize = lm32_uart_realize;
 298}
 299
 300static const TypeInfo lm32_uart_info = {
 301    .name          = TYPE_LM32_UART,
 302    .parent        = TYPE_SYS_BUS_DEVICE,
 303    .instance_size = sizeof(LM32UartState),
 304    .instance_init = lm32_uart_init,
 305    .class_init    = lm32_uart_class_init,
 306};
 307
 308static void lm32_uart_register_types(void)
 309{
 310    type_register_static(&lm32_uart_info);
 311}
 312
 313type_init(lm32_uart_register_types)
 314