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

mchp_pfsoc_dmc.c (6909B)


      1/*
      2 * Microchip PolarFire SoC DDR Memory Controller module emulation
      3 *
      4 * Copyright (c) 2020 Wind River Systems, Inc.
      5 *
      6 * Author:
      7 *   Bin Meng <bin.meng@windriver.com>
      8 *
      9 * This program is free software; you can redistribute it and/or
     10 * modify it under the terms of the GNU General Public License as
     11 * published by the Free Software Foundation; either version 2 or
     12 * (at your option) version 3 of the License.
     13 *
     14 * This program is distributed in the hope that it will be useful,
     15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
     16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     17 * GNU General Public License for more details.
     18 *
     19 * You should have received a copy of the GNU General Public License along
     20 * with this program; if not, see <http://www.gnu.org/licenses/>.
     21 */
     22
     23#include "qemu/osdep.h"
     24#include "qemu/bitops.h"
     25#include "qemu/log.h"
     26#include "qapi/error.h"
     27#include "hw/sysbus.h"
     28#include "hw/misc/mchp_pfsoc_dmc.h"
     29
     30/* DDR SGMII PHY module */
     31
     32#define SGMII_PHY_IOC_REG1              0x208
     33#define SGMII_PHY_TRAINING_STATUS       0x814
     34#define SGMII_PHY_DQ_DQS_ERR_DONE       0x834
     35#define SGMII_PHY_DQDQS_STATUS1         0x84c
     36#define SGMII_PHY_PVT_STAT              0xc20
     37
     38static uint64_t mchp_pfsoc_ddr_sgmii_phy_read(void *opaque, hwaddr offset,
     39                                              unsigned size)
     40{
     41    uint32_t val = 0;
     42    static int training_status_bit;
     43
     44    switch (offset) {
     45    case SGMII_PHY_IOC_REG1:
     46        /* See ddr_pvt_calibration() in HSS */
     47        val = BIT(4) | BIT(2);
     48        break;
     49    case SGMII_PHY_TRAINING_STATUS:
     50        /*
     51         * The codes logic emulates the training status change from
     52         * DDR_TRAINING_IP_SM_BCLKSCLK to DDR_TRAINING_IP_SM_DQ_DQS.
     53         *
     54         * See ddr_setup() in mss_ddr.c in the HSS source codes.
     55         */
     56        val = 1 << training_status_bit;
     57        training_status_bit = (training_status_bit + 1) % 5;
     58        break;
     59    case SGMII_PHY_DQ_DQS_ERR_DONE:
     60        /*
     61         * DDR_TRAINING_IP_SM_VERIFY state in ddr_setup(),
     62         * check that DQ/DQS training passed without error.
     63         */
     64        val = 8;
     65        break;
     66    case SGMII_PHY_DQDQS_STATUS1:
     67        /*
     68         * DDR_TRAINING_IP_SM_VERIFY state in ddr_setup(),
     69         * check that DQ/DQS calculated window is above 5 taps.
     70         */
     71        val = 0xff;
     72        break;
     73    case SGMII_PHY_PVT_STAT:
     74        /* See sgmii_channel_setup() in HSS */
     75        val = BIT(14) | BIT(6);
     76        break;
     77    default:
     78        qemu_log_mask(LOG_UNIMP, "%s: unimplemented device read "
     79                      "(size %d, offset 0x%" HWADDR_PRIx ")\n",
     80                      __func__, size, offset);
     81        break;
     82    }
     83
     84    return val;
     85}
     86
     87static void mchp_pfsoc_ddr_sgmii_phy_write(void *opaque, hwaddr offset,
     88                                           uint64_t value, unsigned size)
     89{
     90    qemu_log_mask(LOG_UNIMP, "%s: unimplemented device write "
     91                  "(size %d, value 0x%" PRIx64
     92                  ", offset 0x%" HWADDR_PRIx ")\n",
     93                  __func__, size, value, offset);
     94}
     95
     96static const MemoryRegionOps mchp_pfsoc_ddr_sgmii_phy_ops = {
     97    .read = mchp_pfsoc_ddr_sgmii_phy_read,
     98    .write = mchp_pfsoc_ddr_sgmii_phy_write,
     99    .endianness = DEVICE_LITTLE_ENDIAN,
    100};
    101
    102static void mchp_pfsoc_ddr_sgmii_phy_realize(DeviceState *dev, Error **errp)
    103{
    104    MchpPfSoCDdrSgmiiPhyState *s = MCHP_PFSOC_DDR_SGMII_PHY(dev);
    105
    106    memory_region_init_io(&s->sgmii_phy, OBJECT(dev),
    107                          &mchp_pfsoc_ddr_sgmii_phy_ops, s,
    108                          "mchp.pfsoc.ddr_sgmii_phy",
    109                          MCHP_PFSOC_DDR_SGMII_PHY_REG_SIZE);
    110    sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->sgmii_phy);
    111}
    112
    113static void mchp_pfsoc_ddr_sgmii_phy_class_init(ObjectClass *klass, void *data)
    114{
    115    DeviceClass *dc = DEVICE_CLASS(klass);
    116
    117    dc->desc = "Microchip PolarFire SoC DDR SGMII PHY module";
    118    dc->realize = mchp_pfsoc_ddr_sgmii_phy_realize;
    119}
    120
    121static const TypeInfo mchp_pfsoc_ddr_sgmii_phy_info = {
    122    .name          = TYPE_MCHP_PFSOC_DDR_SGMII_PHY,
    123    .parent        = TYPE_SYS_BUS_DEVICE,
    124    .instance_size = sizeof(MchpPfSoCDdrSgmiiPhyState),
    125    .class_init    = mchp_pfsoc_ddr_sgmii_phy_class_init,
    126};
    127
    128static void mchp_pfsoc_ddr_sgmii_phy_register_types(void)
    129{
    130    type_register_static(&mchp_pfsoc_ddr_sgmii_phy_info);
    131}
    132
    133type_init(mchp_pfsoc_ddr_sgmii_phy_register_types)
    134
    135/* DDR CFG module */
    136
    137#define CFG_MT_DONE_ACK                 0x4428
    138#define CFG_STAT_DFI_INIT_COMPLETE      0x10034
    139#define CFG_STAT_DFI_TRAINING_COMPLETE  0x10038
    140
    141static uint64_t mchp_pfsoc_ddr_cfg_read(void *opaque, hwaddr offset,
    142                                        unsigned size)
    143{
    144    uint32_t val = 0;
    145
    146    switch (offset) {
    147    case CFG_MT_DONE_ACK:
    148        /* memory test in MTC_test() */
    149        val = BIT(0);
    150        break;
    151    case CFG_STAT_DFI_INIT_COMPLETE:
    152        /* DDR_TRAINING_IP_SM_START_CHECK state in ddr_setup() */
    153        val = BIT(0);
    154        break;
    155    case CFG_STAT_DFI_TRAINING_COMPLETE:
    156        /* DDR_TRAINING_IP_SM_VERIFY state in ddr_setup() */
    157        val = BIT(0);
    158        break;
    159    default:
    160        qemu_log_mask(LOG_UNIMP, "%s: unimplemented device read "
    161                      "(size %d, offset 0x%" HWADDR_PRIx ")\n",
    162                      __func__, size, offset);
    163        break;
    164    }
    165
    166    return val;
    167}
    168
    169static void mchp_pfsoc_ddr_cfg_write(void *opaque, hwaddr offset,
    170                                     uint64_t value, unsigned size)
    171{
    172    qemu_log_mask(LOG_UNIMP, "%s: unimplemented device write "
    173                  "(size %d, value 0x%" PRIx64
    174                  ", offset 0x%" HWADDR_PRIx ")\n",
    175                  __func__, size, value, offset);
    176}
    177
    178static const MemoryRegionOps mchp_pfsoc_ddr_cfg_ops = {
    179    .read = mchp_pfsoc_ddr_cfg_read,
    180    .write = mchp_pfsoc_ddr_cfg_write,
    181    .endianness = DEVICE_LITTLE_ENDIAN,
    182};
    183
    184static void mchp_pfsoc_ddr_cfg_realize(DeviceState *dev, Error **errp)
    185{
    186    MchpPfSoCDdrCfgState *s = MCHP_PFSOC_DDR_CFG(dev);
    187
    188    memory_region_init_io(&s->cfg, OBJECT(dev),
    189                          &mchp_pfsoc_ddr_cfg_ops, s,
    190                          "mchp.pfsoc.ddr_cfg",
    191                          MCHP_PFSOC_DDR_CFG_REG_SIZE);
    192    sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->cfg);
    193}
    194
    195static void mchp_pfsoc_ddr_cfg_class_init(ObjectClass *klass, void *data)
    196{
    197    DeviceClass *dc = DEVICE_CLASS(klass);
    198
    199    dc->desc = "Microchip PolarFire SoC DDR CFG module";
    200    dc->realize = mchp_pfsoc_ddr_cfg_realize;
    201}
    202
    203static const TypeInfo mchp_pfsoc_ddr_cfg_info = {
    204    .name          = TYPE_MCHP_PFSOC_DDR_CFG,
    205    .parent        = TYPE_SYS_BUS_DEVICE,
    206    .instance_size = sizeof(MchpPfSoCDdrCfgState),
    207    .class_init    = mchp_pfsoc_ddr_cfg_class_init,
    208};
    209
    210static void mchp_pfsoc_ddr_cfg_register_types(void)
    211{
    212    type_register_static(&mchp_pfsoc_ddr_cfg_info);
    213}
    214
    215type_init(mchp_pfsoc_ddr_cfg_register_types)