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

omap_uart.c (5212B)


      1/*
      2 * TI OMAP processors UART emulation.
      3 *
      4 * Copyright (C) 2006-2008 Andrzej Zaborowski  <balrog@zabor.org>
      5 * Copyright (C) 2007-2009 Nokia Corporation
      6 *
      7 * This program is free software; you can redistribute it and/or
      8 * modify it under the terms of the GNU General Public License as
      9 * published by the Free Software Foundation; either version 2 or
     10 * (at your option) version 3 of the License.
     11 *
     12 * This program 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
     15 * GNU General Public License 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#include "qemu/osdep.h"
     21#include "chardev/char.h"
     22#include "hw/arm/omap.h"
     23#include "hw/char/serial.h"
     24#include "exec/address-spaces.h"
     25
     26/* UARTs */
     27struct omap_uart_s {
     28    MemoryRegion iomem;
     29    hwaddr base;
     30    SerialMM *serial; /* TODO */
     31    struct omap_target_agent_s *ta;
     32    omap_clk fclk;
     33    qemu_irq irq;
     34
     35    uint8_t eblr;
     36    uint8_t syscontrol;
     37    uint8_t wkup;
     38    uint8_t cfps;
     39    uint8_t mdr[2];
     40    uint8_t scr;
     41    uint8_t clksel;
     42};
     43
     44void omap_uart_reset(struct omap_uart_s *s)
     45{
     46    s->eblr = 0x00;
     47    s->syscontrol = 0;
     48    s->wkup = 0x3f;
     49    s->cfps = 0x69;
     50    s->clksel = 0;
     51}
     52
     53struct omap_uart_s *omap_uart_init(hwaddr base,
     54                qemu_irq irq, omap_clk fclk, omap_clk iclk,
     55                qemu_irq txdma, qemu_irq rxdma,
     56                const char *label, Chardev *chr)
     57{
     58    struct omap_uart_s *s = g_new0(struct omap_uart_s, 1);
     59
     60    s->base = base;
     61    s->fclk = fclk;
     62    s->irq = irq;
     63    s->serial = serial_mm_init(get_system_memory(), base, 2, irq,
     64                               omap_clk_getrate(fclk)/16,
     65                               chr ?: qemu_chr_new(label, "null", NULL),
     66                               DEVICE_NATIVE_ENDIAN);
     67    return s;
     68}
     69
     70static uint64_t omap_uart_read(void *opaque, hwaddr addr,
     71                               unsigned size)
     72{
     73    struct omap_uart_s *s = (struct omap_uart_s *) opaque;
     74
     75    if (size == 4) {
     76        return omap_badwidth_read8(opaque, addr);
     77    }
     78
     79    switch (addr) {
     80    case 0x20:	/* MDR1 */
     81        return s->mdr[0];
     82    case 0x24:	/* MDR2 */
     83        return s->mdr[1];
     84    case 0x40:	/* SCR */
     85        return s->scr;
     86    case 0x44:	/* SSR */
     87        return 0x0;
     88    case 0x48:	/* EBLR (OMAP2) */
     89        return s->eblr;
     90    case 0x4C:	/* OSC_12M_SEL (OMAP1) */
     91        return s->clksel;
     92    case 0x50:	/* MVR */
     93        return 0x30;
     94    case 0x54:	/* SYSC (OMAP2) */
     95        return s->syscontrol;
     96    case 0x58:	/* SYSS (OMAP2) */
     97        return 1;
     98    case 0x5c:	/* WER (OMAP2) */
     99        return s->wkup;
    100    case 0x60:	/* CFPS (OMAP2) */
    101        return s->cfps;
    102    }
    103
    104    OMAP_BAD_REG(addr);
    105    return 0;
    106}
    107
    108static void omap_uart_write(void *opaque, hwaddr addr,
    109                            uint64_t value, unsigned size)
    110{
    111    struct omap_uart_s *s = (struct omap_uart_s *) opaque;
    112
    113    if (size == 4) {
    114        omap_badwidth_write8(opaque, addr, value);
    115        return;
    116    }
    117
    118    switch (addr) {
    119    case 0x20:	/* MDR1 */
    120        s->mdr[0] = value & 0x7f;
    121        break;
    122    case 0x24:	/* MDR2 */
    123        s->mdr[1] = value & 0xff;
    124        break;
    125    case 0x40:	/* SCR */
    126        s->scr = value & 0xff;
    127        break;
    128    case 0x48:	/* EBLR (OMAP2) */
    129        s->eblr = value & 0xff;
    130        break;
    131    case 0x4C:	/* OSC_12M_SEL (OMAP1) */
    132        s->clksel = value & 1;
    133        break;
    134    case 0x44:	/* SSR */
    135    case 0x50:	/* MVR */
    136    case 0x58:	/* SYSS (OMAP2) */
    137        OMAP_RO_REG(addr);
    138        break;
    139    case 0x54:	/* SYSC (OMAP2) */
    140        s->syscontrol = value & 0x1d;
    141        if (value & 2)
    142            omap_uart_reset(s);
    143        break;
    144    case 0x5c:	/* WER (OMAP2) */
    145        s->wkup = value & 0x7f;
    146        break;
    147    case 0x60:	/* CFPS (OMAP2) */
    148        s->cfps = value & 0xff;
    149        break;
    150    default:
    151        OMAP_BAD_REG(addr);
    152    }
    153}
    154
    155static const MemoryRegionOps omap_uart_ops = {
    156    .read = omap_uart_read,
    157    .write = omap_uart_write,
    158    .endianness = DEVICE_NATIVE_ENDIAN,
    159};
    160
    161struct omap_uart_s *omap2_uart_init(MemoryRegion *sysmem,
    162                struct omap_target_agent_s *ta,
    163                qemu_irq irq, omap_clk fclk, omap_clk iclk,
    164                qemu_irq txdma, qemu_irq rxdma,
    165                const char *label, Chardev *chr)
    166{
    167    hwaddr base = omap_l4_attach(ta, 0, NULL);
    168    struct omap_uart_s *s = omap_uart_init(base, irq,
    169                    fclk, iclk, txdma, rxdma, label, chr);
    170
    171    memory_region_init_io(&s->iomem, NULL, &omap_uart_ops, s, "omap.uart", 0x100);
    172
    173    s->ta = ta;
    174
    175    memory_region_add_subregion(sysmem, base + 0x20, &s->iomem);
    176
    177    return s;
    178}
    179
    180void omap_uart_attach(struct omap_uart_s *s, Chardev *chr)
    181{
    182    /* TODO: Should reuse or destroy current s->serial */
    183    s->serial = serial_mm_init(get_system_memory(), s->base, 2, s->irq,
    184                               omap_clk_getrate(s->fclk) / 16,
    185                               chr ?: qemu_chr_new("null", "null", NULL),
    186                               DEVICE_NATIVE_ENDIAN);
    187}