qemu/hw/char/avr_usart.c
<<
>>
Prefs
   1/*
   2 * AVR USART
   3 *
   4 * Copyright (c) 2018 University of Kent
   5 * Author: Sarah Harris
   6 *
   7 * This library is free software; you can redistribute it and/or
   8 * modify it under the terms of the GNU Lesser General Public
   9 * License as published by the Free Software Foundation; either
  10 * version 2.1 of the License, or (at your option) any later version.
  11 *
  12 * This library is distributed in the hope that it will be useful,
  13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  15 * Lesser General Public License for more details.
  16 *
  17 * You should have received a copy of the GNU Lesser General Public
  18 * License along with this library; if not, see
  19 * <http://www.gnu.org/licenses/lgpl-2.1.html>
  20 */
  21
  22#include "qemu/osdep.h"
  23#include "hw/char/avr_usart.h"
  24#include "qemu/log.h"
  25#include "hw/irq.h"
  26#include "hw/qdev-properties.h"
  27#include "hw/qdev-properties-system.h"
  28
  29static int avr_usart_can_receive(void *opaque)
  30{
  31    AVRUsartState *usart = opaque;
  32
  33    if (usart->data_valid || !(usart->csrb & USART_CSRB_RXEN)) {
  34        return 0;
  35    }
  36    return 1;
  37}
  38
  39static void avr_usart_receive(void *opaque, const uint8_t *buffer, int size)
  40{
  41    AVRUsartState *usart = opaque;
  42    assert(size == 1);
  43    assert(!usart->data_valid);
  44    usart->data = buffer[0];
  45    usart->data_valid = true;
  46    usart->csra |= USART_CSRA_RXC;
  47    if (usart->csrb & USART_CSRB_RXCIE) {
  48        qemu_set_irq(usart->rxc_irq, 1);
  49    }
  50}
  51
  52static void update_char_mask(AVRUsartState *usart)
  53{
  54    uint8_t mode = ((usart->csrc & USART_CSRC_CSZ0) ? 1 : 0) |
  55        ((usart->csrc & USART_CSRC_CSZ1) ? 2 : 0) |
  56        ((usart->csrb & USART_CSRB_CSZ2) ? 4 : 0);
  57    switch (mode) {
  58    case 0:
  59        usart->char_mask = 0b11111;
  60        break;
  61    case 1:
  62        usart->char_mask = 0b111111;
  63        break;
  64    case 2:
  65        usart->char_mask = 0b1111111;
  66        break;
  67    case 3:
  68        usart->char_mask = 0b11111111;
  69        break;
  70    case 4:
  71        /* Fallthrough. */
  72    case 5:
  73        /* Fallthrough. */
  74    case 6:
  75        qemu_log_mask(
  76            LOG_GUEST_ERROR,
  77            "%s: Reserved character size 0x%x\n",
  78            __func__,
  79            mode);
  80        break;
  81    case 7:
  82        qemu_log_mask(
  83            LOG_GUEST_ERROR,
  84            "%s: Nine bit character size not supported (forcing eight)\n",
  85            __func__);
  86        usart->char_mask = 0b11111111;
  87        break;
  88    default:
  89        assert(0);
  90    }
  91}
  92
  93static void avr_usart_reset(DeviceState *dev)
  94{
  95    AVRUsartState *usart = AVR_USART(dev);
  96    usart->data_valid = false;
  97    usart->csra = 0b00100000;
  98    usart->csrb = 0b00000000;
  99    usart->csrc = 0b00000110;
 100    usart->brrl = 0;
 101    usart->brrh = 0;
 102    update_char_mask(usart);
 103    qemu_set_irq(usart->rxc_irq, 0);
 104    qemu_set_irq(usart->txc_irq, 0);
 105    qemu_set_irq(usart->dre_irq, 0);
 106}
 107
 108static uint64_t avr_usart_read(void *opaque, hwaddr addr, unsigned int size)
 109{
 110    AVRUsartState *usart = opaque;
 111    uint8_t data;
 112    assert(size == 1);
 113
 114    if (!usart->enabled) {
 115        return 0;
 116    }
 117
 118    switch (addr) {
 119    case USART_DR:
 120        if (!(usart->csrb & USART_CSRB_RXEN)) {
 121            /* Receiver disabled, ignore. */
 122            return 0;
 123        }
 124        if (usart->data_valid) {
 125            data = usart->data & usart->char_mask;
 126            usart->data_valid = false;
 127        } else {
 128            data = 0;
 129        }
 130        usart->csra &= 0xff ^ USART_CSRA_RXC;
 131        qemu_set_irq(usart->rxc_irq, 0);
 132        qemu_chr_fe_accept_input(&usart->chr);
 133        return data;
 134    case USART_CSRA:
 135        return usart->csra;
 136    case USART_CSRB:
 137        return usart->csrb;
 138    case USART_CSRC:
 139        return usart->csrc;
 140    case USART_BRRL:
 141        return usart->brrl;
 142    case USART_BRRH:
 143        return usart->brrh;
 144    default:
 145        qemu_log_mask(
 146            LOG_GUEST_ERROR,
 147            "%s: Bad offset 0x%"HWADDR_PRIx"\n",
 148            __func__,
 149            addr);
 150    }
 151    return 0;
 152}
 153
 154static void avr_usart_write(void *opaque, hwaddr addr, uint64_t value,
 155                                unsigned int size)
 156{
 157    AVRUsartState *usart = opaque;
 158    uint8_t mask;
 159    uint8_t data;
 160    assert((value & 0xff) == value);
 161    assert(size == 1);
 162
 163    if (!usart->enabled) {
 164        return;
 165    }
 166
 167    switch (addr) {
 168    case USART_DR:
 169        if (!(usart->csrb & USART_CSRB_TXEN)) {
 170            /* Transmitter disabled, ignore. */
 171            return;
 172        }
 173        usart->csra |= USART_CSRA_TXC;
 174        usart->csra |= USART_CSRA_DRE;
 175        if (usart->csrb & USART_CSRB_TXCIE) {
 176            qemu_set_irq(usart->txc_irq, 1);
 177            usart->csra &= 0xff ^ USART_CSRA_TXC;
 178        }
 179        if (usart->csrb & USART_CSRB_DREIE) {
 180            qemu_set_irq(usart->dre_irq, 1);
 181        }
 182        data = value;
 183        qemu_chr_fe_write_all(&usart->chr, &data, 1);
 184        break;
 185    case USART_CSRA:
 186        mask = 0b01000011;
 187        /* Mask read-only bits. */
 188        value = (value & mask) | (usart->csra & (0xff ^ mask));
 189        usart->csra = value;
 190        if (value & USART_CSRA_TXC) {
 191            usart->csra ^= USART_CSRA_TXC;
 192            qemu_set_irq(usart->txc_irq, 0);
 193        }
 194        if (value & USART_CSRA_MPCM) {
 195            qemu_log_mask(
 196                LOG_GUEST_ERROR,
 197                "%s: MPCM not supported by USART\n",
 198                __func__);
 199        }
 200        break;
 201    case USART_CSRB:
 202        mask = 0b11111101;
 203        /* Mask read-only bits. */
 204        value = (value & mask) | (usart->csrb & (0xff ^ mask));
 205        usart->csrb = value;
 206        if (!(value & USART_CSRB_RXEN)) {
 207            /* Receiver disabled, flush input buffer. */
 208            usart->data_valid = false;
 209        }
 210        qemu_set_irq(usart->rxc_irq,
 211            ((value & USART_CSRB_RXCIE) &&
 212            (usart->csra & USART_CSRA_RXC)) ? 1 : 0);
 213        qemu_set_irq(usart->txc_irq,
 214            ((value & USART_CSRB_TXCIE) &&
 215            (usart->csra & USART_CSRA_TXC)) ? 1 : 0);
 216        qemu_set_irq(usart->dre_irq,
 217            ((value & USART_CSRB_DREIE) &&
 218            (usart->csra & USART_CSRA_DRE)) ? 1 : 0);
 219        update_char_mask(usart);
 220        break;
 221    case USART_CSRC:
 222        usart->csrc = value;
 223        if ((value & USART_CSRC_MSEL1) && (value & USART_CSRC_MSEL0)) {
 224            qemu_log_mask(
 225                LOG_GUEST_ERROR,
 226                "%s: SPI mode not supported by USART\n",
 227                __func__);
 228        }
 229        if ((value & USART_CSRC_MSEL1) && !(value & USART_CSRC_MSEL0)) {
 230            qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad USART mode\n", __func__);
 231        }
 232        if (!(value & USART_CSRC_PM1) && (value & USART_CSRC_PM0)) {
 233            qemu_log_mask(
 234                LOG_GUEST_ERROR,
 235                "%s: Bad USART parity mode\n",
 236                __func__);
 237        }
 238        update_char_mask(usart);
 239        break;
 240    case USART_BRRL:
 241        usart->brrl = value;
 242        break;
 243    case USART_BRRH:
 244        usart->brrh = value & 0b00001111;
 245        break;
 246    default:
 247        qemu_log_mask(
 248            LOG_GUEST_ERROR,
 249            "%s: Bad offset 0x%"HWADDR_PRIx"\n",
 250            __func__,
 251            addr);
 252    }
 253}
 254
 255static const MemoryRegionOps avr_usart_ops = {
 256    .read = avr_usart_read,
 257    .write = avr_usart_write,
 258    .endianness = DEVICE_NATIVE_ENDIAN,
 259    .impl = {.min_access_size = 1, .max_access_size = 1}
 260};
 261
 262static Property avr_usart_properties[] = {
 263    DEFINE_PROP_CHR("chardev", AVRUsartState, chr),
 264    DEFINE_PROP_END_OF_LIST(),
 265};
 266
 267static void avr_usart_pr(void *opaque, int irq, int level)
 268{
 269    AVRUsartState *s = AVR_USART(opaque);
 270
 271    s->enabled = !level;
 272
 273    if (!s->enabled) {
 274        avr_usart_reset(DEVICE(s));
 275    }
 276}
 277
 278static void avr_usart_init(Object *obj)
 279{
 280    AVRUsartState *s = AVR_USART(obj);
 281    sysbus_init_irq(SYS_BUS_DEVICE(obj), &s->rxc_irq);
 282    sysbus_init_irq(SYS_BUS_DEVICE(obj), &s->dre_irq);
 283    sysbus_init_irq(SYS_BUS_DEVICE(obj), &s->txc_irq);
 284    memory_region_init_io(&s->mmio, obj, &avr_usart_ops, s, TYPE_AVR_USART, 7);
 285    sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->mmio);
 286    qdev_init_gpio_in(DEVICE(s), avr_usart_pr, 1);
 287    s->enabled = true;
 288}
 289
 290static void avr_usart_realize(DeviceState *dev, Error **errp)
 291{
 292    AVRUsartState *s = AVR_USART(dev);
 293    qemu_chr_fe_set_handlers(&s->chr, avr_usart_can_receive,
 294                             avr_usart_receive, NULL, NULL,
 295                             s, NULL, true);
 296    avr_usart_reset(dev);
 297}
 298
 299static void avr_usart_class_init(ObjectClass *klass, void *data)
 300{
 301    DeviceClass *dc = DEVICE_CLASS(klass);
 302
 303    dc->reset = avr_usart_reset;
 304    device_class_set_props(dc, avr_usart_properties);
 305    dc->realize = avr_usart_realize;
 306}
 307
 308static const TypeInfo avr_usart_info = {
 309    .name          = TYPE_AVR_USART,
 310    .parent        = TYPE_SYS_BUS_DEVICE,
 311    .instance_size = sizeof(AVRUsartState),
 312    .instance_init = avr_usart_init,
 313    .class_init    = avr_usart_class_init,
 314};
 315
 316static void avr_usart_register_types(void)
 317{
 318    type_register_static(&avr_usart_info);
 319}
 320
 321type_init(avr_usart_register_types)
 322