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

rx62n.c (10603B)


      1/*
      2 * RX62N Microcontroller
      3 *
      4 * Datasheet: RX62N Group, RX621 Group User's Manual: Hardware
      5 * (Rev.1.40 R01UH0033EJ0140)
      6 *
      7 * Copyright (c) 2019 Yoshinori Sato
      8 * Copyright (c) 2020 Philippe Mathieu-Daudé
      9 *
     10 * This program is free software; you can redistribute it and/or modify it
     11 * under the terms and conditions of the GNU General Public License,
     12 * version 2 or later, as published by the Free Software Foundation.
     13 *
     14 * This program is distributed in the hope it will be useful, but WITHOUT
     15 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
     16 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
     17 * more details.
     18 *
     19 * You should have received a copy of the GNU General Public License along with
     20 * this program.  If not, see <http://www.gnu.org/licenses/>.
     21 */
     22
     23#include "qemu/osdep.h"
     24#include "qapi/error.h"
     25#include "qemu/error-report.h"
     26#include "hw/rx/rx62n.h"
     27#include "hw/loader.h"
     28#include "hw/sysbus.h"
     29#include "hw/qdev-properties.h"
     30#include "sysemu/sysemu.h"
     31#include "qom/object.h"
     32
     33/*
     34 * RX62N Internal Memory
     35 */
     36#define RX62N_IRAM_BASE     0x00000000
     37#define RX62N_DFLASH_BASE   0x00100000
     38#define RX62N_CFLASH_BASE   0xfff80000
     39
     40/*
     41 * RX62N Peripheral Address
     42 * See users manual section 5
     43 */
     44#define RX62N_ICU_BASE  0x00087000
     45#define RX62N_TMR_BASE  0x00088200
     46#define RX62N_CMT_BASE  0x00088000
     47#define RX62N_SCI_BASE  0x00088240
     48
     49/*
     50 * RX62N Peripheral IRQ
     51 * See users manual section 11
     52 */
     53#define RX62N_TMR_IRQ   174
     54#define RX62N_CMT_IRQ   28
     55#define RX62N_SCI_IRQ   214
     56
     57#define RX62N_XTAL_MIN_HZ  (8 * 1000 * 1000)
     58#define RX62N_XTAL_MAX_HZ (14 * 1000 * 1000)
     59#define RX62N_PCLK_MAX_HZ (50 * 1000 * 1000)
     60
     61struct RX62NClass {
     62    /*< private >*/
     63    DeviceClass parent_class;
     64    /*< public >*/
     65    const char *name;
     66    uint64_t ram_size;
     67    uint64_t rom_flash_size;
     68    uint64_t data_flash_size;
     69};
     70typedef struct RX62NClass RX62NClass;
     71
     72DECLARE_CLASS_CHECKERS(RX62NClass, RX62N_MCU,
     73                       TYPE_RX62N_MCU)
     74
     75/*
     76 * IRQ -> IPR mapping table
     77 * 0x00 - 0x91: IPR no (IPR00 to IPR91)
     78 * 0xff: IPR not assigned
     79 * See "11.3.1 Interrupt Vector Table" in hardware manual.
     80 */
     81static const uint8_t ipr_table[NR_IRQS] = {
     82    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
     83    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 15 */
     84    0x00, 0xff, 0xff, 0xff, 0xff, 0x01, 0xff, 0x02,
     85    0xff, 0xff, 0xff, 0x03, 0x04, 0x05, 0x06, 0x07, /* 31 */
     86    0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
     87    0x10, 0x11, 0x12, 0x13, 0x14, 0x14, 0x14, 0x14, /* 47 */
     88    0x15, 0x15, 0x15, 0x15, 0xff, 0xff, 0xff, 0xff,
     89    0x18, 0x18, 0x18, 0x18, 0x18, 0x1d, 0x1e, 0x1f, /* 63 */
     90    0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
     91    0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, /* 79 */
     92    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
     93    0xff, 0xff, 0x3a, 0x3b, 0x3c, 0xff, 0xff, 0xff, /* 95 */
     94    0x40, 0xff, 0x44, 0x45, 0xff, 0xff, 0x48, 0xff,
     95    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 111 */
     96    0xff, 0xff, 0x51, 0x51, 0x51, 0x51, 0x52, 0x52,
     97    0x52, 0x53, 0x53, 0x54, 0x54, 0x55, 0x55, 0x56, /* 127 */
     98    0x56, 0x57, 0x57, 0x57, 0x57, 0x58, 0x59, 0x59,
     99    0x59, 0x59, 0x5a, 0x5b, 0x5b, 0x5b, 0x5c, 0x5c, /* 143 */
    100    0x5c, 0x5c, 0x5d, 0x5d, 0x5d, 0x5e, 0x5e, 0x5f,
    101    0x5f, 0x60, 0x60, 0x61, 0x61, 0x62, 0x62, 0x62, /* 159 */
    102    0x62, 0x63, 0x64, 0x64, 0x64, 0x64, 0x65, 0x66,
    103    0x66, 0x66, 0x67, 0x67, 0x67, 0x67, 0x68, 0x68, /* 175 */
    104    0x68, 0x69, 0x69, 0x69, 0x6a, 0x6a, 0x6a, 0x6b,
    105    0x6b, 0x6b, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 191 */
    106    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x70, 0x71,
    107    0x72, 0x73, 0x74, 0x75, 0xff, 0xff, 0xff, 0xff, /* 207 */
    108    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x80,
    109    0x80, 0x80, 0x81, 0x81, 0x81, 0x81, 0x82, 0x82, /* 223 */
    110    0x82, 0x82, 0x83, 0x83, 0x83, 0x83, 0xff, 0xff,
    111    0xff, 0xff, 0x85, 0x85, 0x85, 0x85, 0x86, 0x86, /* 239 */
    112    0x86, 0x86, 0xff, 0xff, 0xff, 0xff, 0x88, 0x89,
    113    0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x91, /* 255 */
    114};
    115
    116/*
    117 * Level triggerd IRQ list
    118 * Not listed IRQ is Edge trigger.
    119 * See "11.3.1 Interrupt Vector Table" in hardware manual.
    120 */
    121static const uint8_t levelirq[] = {
    122     16,  21,  32,  44,  47,  48,  51,  64,  65,  66,
    123     67,  68,  69,  70,  71,  72,  73,  74,  75,  76,
    124     77,  78,  79,  90,  91, 170, 171, 172, 173, 214,
    125    217, 218, 221, 222, 225, 226, 229, 234, 237, 238,
    126    241, 246, 249, 250, 253,
    127};
    128
    129static void register_icu(RX62NState *s)
    130{
    131    int i;
    132    SysBusDevice *icu;
    133
    134    object_initialize_child(OBJECT(s), "icu", &s->icu, TYPE_RX_ICU);
    135    icu = SYS_BUS_DEVICE(&s->icu);
    136    qdev_prop_set_uint32(DEVICE(icu), "len-ipr-map", NR_IRQS);
    137    for (i = 0; i < NR_IRQS; i++) {
    138        char propname[32];
    139        snprintf(propname, sizeof(propname), "ipr-map[%d]", i);
    140        qdev_prop_set_uint32(DEVICE(icu), propname, ipr_table[i]);
    141    }
    142    qdev_prop_set_uint32(DEVICE(icu), "len-trigger-level",
    143                         ARRAY_SIZE(levelirq));
    144    for (i = 0; i < ARRAY_SIZE(levelirq); i++) {
    145        char propname[32];
    146        snprintf(propname, sizeof(propname), "trigger-level[%d]", i);
    147        qdev_prop_set_uint32(DEVICE(icu), propname, levelirq[i]);
    148    }
    149
    150    for (i = 0; i < NR_IRQS; i++) {
    151        s->irq[i] = qdev_get_gpio_in(DEVICE(icu), i);
    152    }
    153    sysbus_realize(icu, &error_abort);
    154    sysbus_connect_irq(icu, 0, qdev_get_gpio_in(DEVICE(&s->cpu), RX_CPU_IRQ));
    155    sysbus_connect_irq(icu, 1, qdev_get_gpio_in(DEVICE(&s->cpu), RX_CPU_FIR));
    156    sysbus_connect_irq(icu, 2, s->irq[SWI]);
    157    sysbus_mmio_map(SYS_BUS_DEVICE(icu), 0, RX62N_ICU_BASE);
    158}
    159
    160static void register_tmr(RX62NState *s, int unit)
    161{
    162    SysBusDevice *tmr;
    163    int i, irqbase;
    164
    165    object_initialize_child(OBJECT(s), "tmr[*]",
    166                            &s->tmr[unit], TYPE_RENESAS_TMR);
    167    tmr = SYS_BUS_DEVICE(&s->tmr[unit]);
    168    qdev_prop_set_uint64(DEVICE(tmr), "input-freq", s->pclk_freq_hz);
    169    sysbus_realize(tmr, &error_abort);
    170
    171    irqbase = RX62N_TMR_IRQ + TMR_NR_IRQ * unit;
    172    for (i = 0; i < TMR_NR_IRQ; i++) {
    173        sysbus_connect_irq(tmr, i, s->irq[irqbase + i]);
    174    }
    175    sysbus_mmio_map(tmr, 0, RX62N_TMR_BASE + unit * 0x10);
    176}
    177
    178static void register_cmt(RX62NState *s, int unit)
    179{
    180    SysBusDevice *cmt;
    181    int i, irqbase;
    182
    183    object_initialize_child(OBJECT(s), "cmt[*]",
    184                            &s->cmt[unit], TYPE_RENESAS_CMT);
    185    cmt = SYS_BUS_DEVICE(&s->cmt[unit]);
    186    qdev_prop_set_uint64(DEVICE(cmt), "input-freq", s->pclk_freq_hz);
    187    sysbus_realize(cmt, &error_abort);
    188
    189    irqbase = RX62N_CMT_IRQ + CMT_NR_IRQ * unit;
    190    for (i = 0; i < CMT_NR_IRQ; i++) {
    191        sysbus_connect_irq(cmt, i, s->irq[irqbase + i]);
    192    }
    193    sysbus_mmio_map(cmt, 0, RX62N_CMT_BASE + unit * 0x10);
    194}
    195
    196static void register_sci(RX62NState *s, int unit)
    197{
    198    SysBusDevice *sci;
    199    int i, irqbase;
    200
    201    object_initialize_child(OBJECT(s), "sci[*]",
    202                            &s->sci[unit], TYPE_RENESAS_SCI);
    203    sci = SYS_BUS_DEVICE(&s->sci[unit]);
    204    qdev_prop_set_chr(DEVICE(sci), "chardev", serial_hd(unit));
    205    qdev_prop_set_uint64(DEVICE(sci), "input-freq", s->pclk_freq_hz);
    206    sysbus_realize(sci, &error_abort);
    207
    208    irqbase = RX62N_SCI_IRQ + SCI_NR_IRQ * unit;
    209    for (i = 0; i < SCI_NR_IRQ; i++) {
    210        sysbus_connect_irq(sci, i, s->irq[irqbase + i]);
    211    }
    212    sysbus_mmio_map(sci, 0, RX62N_SCI_BASE + unit * 0x08);
    213}
    214
    215static void rx62n_realize(DeviceState *dev, Error **errp)
    216{
    217    RX62NState *s = RX62N_MCU(dev);
    218    RX62NClass *rxc = RX62N_MCU_GET_CLASS(dev);
    219
    220    if (s->xtal_freq_hz == 0) {
    221        error_setg(errp, "\"xtal-frequency-hz\" property must be provided.");
    222        return;
    223    }
    224    /* XTAL range: 8-14 MHz */
    225    if (s->xtal_freq_hz < RX62N_XTAL_MIN_HZ
    226            || s->xtal_freq_hz > RX62N_XTAL_MAX_HZ) {
    227        error_setg(errp, "\"xtal-frequency-hz\" property in incorrect range.");
    228        return;
    229    }
    230    /* Use a 4x fixed multiplier */
    231    s->pclk_freq_hz = 4 * s->xtal_freq_hz;
    232    /* PCLK range: 8-50 MHz */
    233    assert(s->pclk_freq_hz <= RX62N_PCLK_MAX_HZ);
    234
    235    memory_region_init_ram(&s->iram, OBJECT(dev), "iram",
    236                           rxc->ram_size, &error_abort);
    237    memory_region_add_subregion(s->sysmem, RX62N_IRAM_BASE, &s->iram);
    238    memory_region_init_rom(&s->d_flash, OBJECT(dev), "flash-data",
    239                           rxc->data_flash_size, &error_abort);
    240    memory_region_add_subregion(s->sysmem, RX62N_DFLASH_BASE, &s->d_flash);
    241    memory_region_init_rom(&s->c_flash, OBJECT(dev), "flash-code",
    242                           rxc->rom_flash_size, &error_abort);
    243    memory_region_add_subregion(s->sysmem, RX62N_CFLASH_BASE, &s->c_flash);
    244
    245    /* Initialize CPU */
    246    object_initialize_child(OBJECT(s), "cpu", &s->cpu, TYPE_RX62N_CPU);
    247    qdev_realize(DEVICE(&s->cpu), NULL, &error_abort);
    248
    249    register_icu(s);
    250    s->cpu.env.ack = qdev_get_gpio_in_named(DEVICE(&s->icu), "ack", 0);
    251    register_tmr(s, 0);
    252    register_tmr(s, 1);
    253    register_cmt(s, 0);
    254    register_cmt(s, 1);
    255    register_sci(s, 0);
    256}
    257
    258static Property rx62n_properties[] = {
    259    DEFINE_PROP_LINK("main-bus", RX62NState, sysmem, TYPE_MEMORY_REGION,
    260                     MemoryRegion *),
    261    DEFINE_PROP_BOOL("load-kernel", RX62NState, kernel, false),
    262    DEFINE_PROP_UINT32("xtal-frequency-hz", RX62NState, xtal_freq_hz, 0),
    263    DEFINE_PROP_END_OF_LIST(),
    264};
    265
    266static void rx62n_class_init(ObjectClass *klass, void *data)
    267{
    268    DeviceClass *dc = DEVICE_CLASS(klass);
    269
    270    dc->realize = rx62n_realize;
    271    device_class_set_props(dc, rx62n_properties);
    272}
    273
    274static void r5f562n7_class_init(ObjectClass *oc, void *data)
    275{
    276    RX62NClass *rxc = RX62N_MCU_CLASS(oc);
    277
    278    rxc->ram_size = 64 * KiB;
    279    rxc->rom_flash_size = 384 * KiB;
    280    rxc->data_flash_size = 32 * KiB;
    281};
    282
    283static void r5f562n8_class_init(ObjectClass *oc, void *data)
    284{
    285    RX62NClass *rxc = RX62N_MCU_CLASS(oc);
    286
    287    rxc->ram_size = 96 * KiB;
    288    rxc->rom_flash_size = 512 * KiB;
    289    rxc->data_flash_size = 32 * KiB;
    290};
    291
    292static const TypeInfo rx62n_types[] = {
    293    {
    294        .name           = TYPE_R5F562N7_MCU,
    295        .parent         = TYPE_RX62N_MCU,
    296        .class_init     = r5f562n7_class_init,
    297    }, {
    298        .name           = TYPE_R5F562N8_MCU,
    299        .parent         = TYPE_RX62N_MCU,
    300        .class_init     = r5f562n8_class_init,
    301    }, {
    302        .name           = TYPE_RX62N_MCU,
    303        .parent         = TYPE_DEVICE,
    304        .instance_size  = sizeof(RX62NState),
    305        .class_size     = sizeof(RX62NClass),
    306        .class_init     = rx62n_class_init,
    307        .abstract       = true,
    308     }
    309};
    310
    311DEFINE_TYPES(rx62n_types)