qemu

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

imx_serial.c (10474B)


      1 /*
      2  * IMX31 UARTS
      3  *
      4  * Copyright (c) 2008 OKL
      5  * Originally Written by Hans Jiang
      6  * Copyright (c) 2011 NICTA Pty Ltd.
      7  * Updated by Jean-Christophe Dubois <jcd@tribudubois.net>
      8  *
      9  * This work is licensed under the terms of the GNU GPL, version 2 or later.
     10  * See the COPYING file in the top-level directory.
     11  *
     12  * This is a `bare-bones' implementation of the IMX series serial ports.
     13  * TODO:
     14  *  -- implement FIFOs.  The real hardware has 32 word transmit
     15  *                       and receive FIFOs; we currently use a 1-char buffer
     16  *  -- implement DMA
     17  *  -- implement BAUD-rate and modem lines, for when the backend
     18  *     is a real serial device.
     19  */
     20 
     21 #include "qemu/osdep.h"
     22 #include "hw/char/imx_serial.h"
     23 #include "hw/irq.h"
     24 #include "hw/qdev-properties.h"
     25 #include "hw/qdev-properties-system.h"
     26 #include "migration/vmstate.h"
     27 #include "qemu/log.h"
     28 #include "qemu/module.h"
     29 
     30 #ifndef DEBUG_IMX_UART
     31 #define DEBUG_IMX_UART 0
     32 #endif
     33 
     34 #define DPRINTF(fmt, args...) \
     35     do { \
     36         if (DEBUG_IMX_UART) { \
     37             fprintf(stderr, "[%s]%s: " fmt , TYPE_IMX_SERIAL, \
     38                                              __func__, ##args); \
     39         } \
     40     } while (0)
     41 
     42 static const VMStateDescription vmstate_imx_serial = {
     43     .name = TYPE_IMX_SERIAL,
     44     .version_id = 2,
     45     .minimum_version_id = 2,
     46     .fields = (VMStateField[]) {
     47         VMSTATE_INT32(readbuff, IMXSerialState),
     48         VMSTATE_UINT32(usr1, IMXSerialState),
     49         VMSTATE_UINT32(usr2, IMXSerialState),
     50         VMSTATE_UINT32(ucr1, IMXSerialState),
     51         VMSTATE_UINT32(uts1, IMXSerialState),
     52         VMSTATE_UINT32(onems, IMXSerialState),
     53         VMSTATE_UINT32(ufcr, IMXSerialState),
     54         VMSTATE_UINT32(ubmr, IMXSerialState),
     55         VMSTATE_UINT32(ubrc, IMXSerialState),
     56         VMSTATE_UINT32(ucr3, IMXSerialState),
     57         VMSTATE_UINT32(ucr4, IMXSerialState),
     58         VMSTATE_END_OF_LIST()
     59     },
     60 };
     61 
     62 static void imx_update(IMXSerialState *s)
     63 {
     64     uint32_t usr1;
     65     uint32_t usr2;
     66     uint32_t mask;
     67 
     68     /*
     69      * Lucky for us TRDY and RRDY has the same offset in both USR1 and
     70      * UCR1, so we can get away with something as simple as the
     71      * following:
     72      */
     73     usr1 = s->usr1 & s->ucr1 & (USR1_TRDY | USR1_RRDY);
     74     /*
     75      * Bits that we want in USR2 are not as conveniently laid out,
     76      * unfortunately.
     77      */
     78     mask = (s->ucr1 & UCR1_TXMPTYEN) ? USR2_TXFE : 0;
     79     /*
     80      * TCEN and TXDC are both bit 3
     81      * RDR and DREN are both bit 0
     82      */
     83     mask |= s->ucr4 & (UCR4_TCEN | UCR4_DREN);
     84 
     85     usr2 = s->usr2 & mask;
     86 
     87     qemu_set_irq(s->irq, usr1 || usr2);
     88 }
     89 
     90 static void imx_serial_reset(IMXSerialState *s)
     91 {
     92 
     93     s->usr1 = USR1_TRDY | USR1_RXDS;
     94     /*
     95      * Fake attachment of a terminal: assert RTS.
     96      */
     97     s->usr1 |= USR1_RTSS;
     98     s->usr2 = USR2_TXFE | USR2_TXDC | USR2_DCDIN;
     99     s->uts1 = UTS1_RXEMPTY | UTS1_TXEMPTY;
    100     s->ucr1 = 0;
    101     s->ucr2 = UCR2_SRST;
    102     s->ucr3 = 0x700;
    103     s->ubmr = 0;
    104     s->ubrc = 4;
    105     s->readbuff = URXD_ERR;
    106 }
    107 
    108 static void imx_serial_reset_at_boot(DeviceState *dev)
    109 {
    110     IMXSerialState *s = IMX_SERIAL(dev);
    111 
    112     imx_serial_reset(s);
    113 
    114     /*
    115      * enable the uart on boot, so messages from the linux decompresser
    116      * are visible.  On real hardware this is done by the boot rom
    117      * before anything else is loaded.
    118      */
    119     s->ucr1 = UCR1_UARTEN;
    120     s->ucr2 = UCR2_TXEN;
    121 
    122 }
    123 
    124 static uint64_t imx_serial_read(void *opaque, hwaddr offset,
    125                                 unsigned size)
    126 {
    127     IMXSerialState *s = (IMXSerialState *)opaque;
    128     uint32_t c;
    129 
    130     DPRINTF("read(offset=0x%" HWADDR_PRIx ")\n", offset);
    131 
    132     switch (offset >> 2) {
    133     case 0x0: /* URXD */
    134         c = s->readbuff;
    135         if (!(s->uts1 & UTS1_RXEMPTY)) {
    136             /* Character is valid */
    137             c |= URXD_CHARRDY;
    138             s->usr1 &= ~USR1_RRDY;
    139             s->usr2 &= ~USR2_RDR;
    140             s->uts1 |= UTS1_RXEMPTY;
    141             imx_update(s);
    142             qemu_chr_fe_accept_input(&s->chr);
    143         }
    144         return c;
    145 
    146     case 0x20: /* UCR1 */
    147         return s->ucr1;
    148 
    149     case 0x21: /* UCR2 */
    150         return s->ucr2;
    151 
    152     case 0x25: /* USR1 */
    153         return s->usr1;
    154 
    155     case 0x26: /* USR2 */
    156         return s->usr2;
    157 
    158     case 0x2A: /* BRM Modulator */
    159         return s->ubmr;
    160 
    161     case 0x2B: /* Baud Rate Count */
    162         return s->ubrc;
    163 
    164     case 0x2d: /* Test register */
    165         return s->uts1;
    166 
    167     case 0x24: /* UFCR */
    168         return s->ufcr;
    169 
    170     case 0x2c:
    171         return s->onems;
    172 
    173     case 0x22: /* UCR3 */
    174         return s->ucr3;
    175 
    176     case 0x23: /* UCR4 */
    177         return s->ucr4;
    178 
    179     case 0x29: /* BRM Incremental */
    180         return 0x0; /* TODO */
    181 
    182     default:
    183         qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: Bad register at offset 0x%"
    184                       HWADDR_PRIx "\n", TYPE_IMX_SERIAL, __func__, offset);
    185         return 0;
    186     }
    187 }
    188 
    189 static void imx_serial_write(void *opaque, hwaddr offset,
    190                              uint64_t value, unsigned size)
    191 {
    192     IMXSerialState *s = (IMXSerialState *)opaque;
    193     Chardev *chr = qemu_chr_fe_get_driver(&s->chr);
    194     unsigned char ch;
    195 
    196     DPRINTF("write(offset=0x%" HWADDR_PRIx ", value = 0x%x) to %s\n",
    197             offset, (unsigned int)value, chr ? chr->label : "NODEV");
    198 
    199     switch (offset >> 2) {
    200     case 0x10: /* UTXD */
    201         ch = value;
    202         if (s->ucr2 & UCR2_TXEN) {
    203             /* XXX this blocks entire thread. Rewrite to use
    204              * qemu_chr_fe_write and background I/O callbacks */
    205             qemu_chr_fe_write_all(&s->chr, &ch, 1);
    206             s->usr1 &= ~USR1_TRDY;
    207             s->usr2 &= ~USR2_TXDC;
    208             imx_update(s);
    209             s->usr1 |= USR1_TRDY;
    210             s->usr2 |= USR2_TXDC;
    211             imx_update(s);
    212         }
    213         break;
    214 
    215     case 0x20: /* UCR1 */
    216         s->ucr1 = value & 0xffff;
    217 
    218         DPRINTF("write(ucr1=%x)\n", (unsigned int)value);
    219 
    220         imx_update(s);
    221         break;
    222 
    223     case 0x21: /* UCR2 */
    224         /*
    225          * Only a few bits in control register 2 are implemented as yet.
    226          * If it's intended to use a real serial device as a back-end, this
    227          * register will have to be implemented more fully.
    228          */
    229         if (!(value & UCR2_SRST)) {
    230             imx_serial_reset(s);
    231             imx_update(s);
    232             value |= UCR2_SRST;
    233         }
    234         if (value & UCR2_RXEN) {
    235             if (!(s->ucr2 & UCR2_RXEN)) {
    236                 qemu_chr_fe_accept_input(&s->chr);
    237             }
    238         }
    239         s->ucr2 = value & 0xffff;
    240         break;
    241 
    242     case 0x25: /* USR1 */
    243         value &= USR1_AWAKE | USR1_AIRINT | USR1_DTRD | USR1_AGTIM |
    244                  USR1_FRAMERR | USR1_ESCF | USR1_RTSD | USR1_PARTYER;
    245         s->usr1 &= ~value;
    246         break;
    247 
    248     case 0x26: /* USR2 */
    249         /*
    250          * Writing 1 to some bits clears them; all other
    251          * values are ignored
    252          */
    253         value &= USR2_ADET | USR2_DTRF | USR2_IDLE | USR2_ACST |
    254                  USR2_RIDELT | USR2_IRINT | USR2_WAKE |
    255                  USR2_DCDDELT | USR2_RTSF | USR2_BRCD | USR2_ORE;
    256         s->usr2 &= ~value;
    257         break;
    258 
    259     /*
    260      * Linux expects to see what it writes to these registers
    261      * We don't currently alter the baud rate
    262      */
    263     case 0x29: /* UBIR */
    264         s->ubrc = value & 0xffff;
    265         break;
    266 
    267     case 0x2a: /* UBMR */
    268         s->ubmr = value & 0xffff;
    269         break;
    270 
    271     case 0x2c: /* One ms reg */
    272         s->onems = value & 0xffff;
    273         break;
    274 
    275     case 0x24: /* FIFO control register */
    276         s->ufcr = value & 0xffff;
    277         break;
    278 
    279     case 0x22: /* UCR3 */
    280         s->ucr3 = value & 0xffff;
    281         break;
    282 
    283     case 0x23: /* UCR4 */
    284         s->ucr4 = value & 0xffff;
    285         imx_update(s);
    286         break;
    287 
    288     case 0x2d: /* UTS1 */
    289         qemu_log_mask(LOG_UNIMP, "[%s]%s: Unimplemented reg 0x%"
    290                       HWADDR_PRIx "\n", TYPE_IMX_SERIAL, __func__, offset);
    291         /* TODO */
    292         break;
    293 
    294     default:
    295         qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: Bad register at offset 0x%"
    296                       HWADDR_PRIx "\n", TYPE_IMX_SERIAL, __func__, offset);
    297     }
    298 }
    299 
    300 static int imx_can_receive(void *opaque)
    301 {
    302     IMXSerialState *s = (IMXSerialState *)opaque;
    303     return !(s->usr1 & USR1_RRDY);
    304 }
    305 
    306 static void imx_put_data(void *opaque, uint32_t value)
    307 {
    308     IMXSerialState *s = (IMXSerialState *)opaque;
    309 
    310     DPRINTF("received char\n");
    311 
    312     s->usr1 |= USR1_RRDY;
    313     s->usr2 |= USR2_RDR;
    314     s->uts1 &= ~UTS1_RXEMPTY;
    315     s->readbuff = value;
    316     if (value & URXD_BRK) {
    317         s->usr2 |= USR2_BRCD;
    318     }
    319     imx_update(s);
    320 }
    321 
    322 static void imx_receive(void *opaque, const uint8_t *buf, int size)
    323 {
    324     imx_put_data(opaque, *buf);
    325 }
    326 
    327 static void imx_event(void *opaque, QEMUChrEvent event)
    328 {
    329     if (event == CHR_EVENT_BREAK) {
    330         imx_put_data(opaque, URXD_BRK | URXD_FRMERR | URXD_ERR);
    331     }
    332 }
    333 
    334 
    335 static const struct MemoryRegionOps imx_serial_ops = {
    336     .read = imx_serial_read,
    337     .write = imx_serial_write,
    338     .endianness = DEVICE_NATIVE_ENDIAN,
    339 };
    340 
    341 static void imx_serial_realize(DeviceState *dev, Error **errp)
    342 {
    343     IMXSerialState *s = IMX_SERIAL(dev);
    344 
    345     DPRINTF("char dev for uart: %p\n", qemu_chr_fe_get_driver(&s->chr));
    346 
    347     qemu_chr_fe_set_handlers(&s->chr, imx_can_receive, imx_receive,
    348                              imx_event, NULL, s, NULL, true);
    349 }
    350 
    351 static void imx_serial_init(Object *obj)
    352 {
    353     SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
    354     IMXSerialState *s = IMX_SERIAL(obj);
    355 
    356     memory_region_init_io(&s->iomem, obj, &imx_serial_ops, s,
    357                           TYPE_IMX_SERIAL, 0x1000);
    358     sysbus_init_mmio(sbd, &s->iomem);
    359     sysbus_init_irq(sbd, &s->irq);
    360 }
    361 
    362 static Property imx_serial_properties[] = {
    363     DEFINE_PROP_CHR("chardev", IMXSerialState, chr),
    364     DEFINE_PROP_END_OF_LIST(),
    365 };
    366 
    367 static void imx_serial_class_init(ObjectClass *klass, void *data)
    368 {
    369     DeviceClass *dc = DEVICE_CLASS(klass);
    370 
    371     dc->realize = imx_serial_realize;
    372     dc->vmsd = &vmstate_imx_serial;
    373     dc->reset = imx_serial_reset_at_boot;
    374     set_bit(DEVICE_CATEGORY_INPUT, dc->categories);
    375     dc->desc = "i.MX series UART";
    376     device_class_set_props(dc, imx_serial_properties);
    377 }
    378 
    379 static const TypeInfo imx_serial_info = {
    380     .name           = TYPE_IMX_SERIAL,
    381     .parent         = TYPE_SYS_BUS_DEVICE,
    382     .instance_size  = sizeof(IMXSerialState),
    383     .instance_init  = imx_serial_init,
    384     .class_init     = imx_serial_class_init,
    385 };
    386 
    387 static void imx_serial_register_types(void)
    388 {
    389     type_register_static(&imx_serial_info);
    390 }
    391 
    392 type_init(imx_serial_register_types)