qemu/hw/misc/mchp_pfsoc_ioscb.c
<<
>>
Prefs
   1/*
   2 * Microchip PolarFire SoC IOSCB 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_ioscb.h"
  29
  30/*
  31 * The whole IOSCB module registers map into the system address at 0x3000_0000,
  32 * named as "System Port 0 (AXI-D0)".
  33 */
  34#define IOSCB_WHOLE_REG_SIZE        0x10000000
  35#define IOSCB_SUBMOD_REG_SIZE       0x1000
  36
  37/*
  38 * There are many sub-modules in the IOSCB module.
  39 * See Microchip PolarFire SoC documentation (Register_Map.zip),
  40 * Register Map/PF_SoC_RegMap_V1_1/MPFS250T/mpfs250t_ioscb_memmap_dri.htm
  41 *
  42 * The following are sub-modules offsets that are of concern.
  43 */
  44#define IOSCB_LANE01_BASE           0x06500000
  45#define IOSCB_LANE23_BASE           0x06510000
  46#define IOSCB_CTRL_BASE             0x07020000
  47#define IOSCB_CFG_BASE              0x07080000
  48#define IOSCB_PLL_MSS_BASE          0x0E001000
  49#define IOSCB_CFM_MSS_BASE          0x0E002000
  50#define IOSCB_PLL_DDR_BASE          0x0E010000
  51#define IOSCB_BC_DDR_BASE           0x0E020000
  52#define IOSCB_IO_CALIB_DDR_BASE     0x0E040000
  53#define IOSCB_PLL_SGMII_BASE        0x0E080000
  54#define IOSCB_DLL_SGMII_BASE        0x0E100000
  55#define IOSCB_CFM_SGMII_BASE        0x0E200000
  56#define IOSCB_BC_SGMII_BASE         0x0E400000
  57#define IOSCB_IO_CALIB_SGMII_BASE   0x0E800000
  58
  59static uint64_t mchp_pfsoc_dummy_read(void *opaque, hwaddr offset,
  60                                      unsigned size)
  61{
  62    qemu_log_mask(LOG_UNIMP, "%s: unimplemented device read "
  63                  "(size %d, offset 0x%" HWADDR_PRIx ")\n",
  64                  __func__, size, offset);
  65
  66    return 0;
  67}
  68
  69static void mchp_pfsoc_dummy_write(void *opaque, hwaddr offset,
  70                                   uint64_t value, unsigned size)
  71{
  72    qemu_log_mask(LOG_UNIMP, "%s: unimplemented device write "
  73                  "(size %d, value 0x%" PRIx64
  74                  ", offset 0x%" HWADDR_PRIx ")\n",
  75                  __func__, size, value, offset);
  76}
  77
  78static const MemoryRegionOps mchp_pfsoc_dummy_ops = {
  79    .read = mchp_pfsoc_dummy_read,
  80    .write = mchp_pfsoc_dummy_write,
  81    .endianness = DEVICE_LITTLE_ENDIAN,
  82};
  83
  84/* All PLL modules in IOSCB have the same register layout */
  85
  86#define PLL_CTRL    0x04
  87
  88static uint64_t mchp_pfsoc_pll_read(void *opaque, hwaddr offset,
  89                                    unsigned size)
  90{
  91    uint32_t val = 0;
  92
  93    switch (offset) {
  94    case PLL_CTRL:
  95        /* PLL is locked */
  96        val = BIT(25);
  97        break;
  98    default:
  99        qemu_log_mask(LOG_UNIMP, "%s: unimplemented device read "
 100                      "(size %d, offset 0x%" HWADDR_PRIx ")\n",
 101                      __func__, size, offset);
 102        break;
 103    }
 104
 105    return val;
 106}
 107
 108static const MemoryRegionOps mchp_pfsoc_pll_ops = {
 109    .read = mchp_pfsoc_pll_read,
 110    .write = mchp_pfsoc_dummy_write,
 111    .endianness = DEVICE_LITTLE_ENDIAN,
 112};
 113
 114/* IO_CALIB_DDR submodule */
 115
 116#define IO_CALIB_DDR_IOC_REG1   0x08
 117
 118static uint64_t mchp_pfsoc_io_calib_ddr_read(void *opaque, hwaddr offset,
 119                                             unsigned size)
 120{
 121    uint32_t val = 0;
 122
 123    switch (offset) {
 124    case IO_CALIB_DDR_IOC_REG1:
 125        /* calibration completed */
 126        val = BIT(2);
 127        break;
 128    default:
 129        qemu_log_mask(LOG_UNIMP, "%s: unimplemented device read "
 130                      "(size %d, offset 0x%" HWADDR_PRIx ")\n",
 131                      __func__, size, offset);
 132        break;
 133    }
 134
 135    return val;
 136}
 137
 138static const MemoryRegionOps mchp_pfsoc_io_calib_ddr_ops = {
 139    .read = mchp_pfsoc_io_calib_ddr_read,
 140    .write = mchp_pfsoc_dummy_write,
 141    .endianness = DEVICE_LITTLE_ENDIAN,
 142};
 143
 144static void mchp_pfsoc_ioscb_realize(DeviceState *dev, Error **errp)
 145{
 146    MchpPfSoCIoscbState *s = MCHP_PFSOC_IOSCB(dev);
 147    SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
 148
 149    memory_region_init(&s->container, OBJECT(s),
 150                       "mchp.pfsoc.ioscb", IOSCB_WHOLE_REG_SIZE);
 151    sysbus_init_mmio(sbd, &s->container);
 152
 153    /* add subregions for all sub-modules in IOSCB */
 154
 155    memory_region_init_io(&s->lane01, OBJECT(s), &mchp_pfsoc_dummy_ops, s,
 156                          "mchp.pfsoc.ioscb.lane01", IOSCB_SUBMOD_REG_SIZE);
 157    memory_region_add_subregion(&s->container, IOSCB_LANE01_BASE, &s->lane01);
 158
 159    memory_region_init_io(&s->lane23, OBJECT(s), &mchp_pfsoc_dummy_ops, s,
 160                          "mchp.pfsoc.ioscb.lane23", IOSCB_SUBMOD_REG_SIZE);
 161    memory_region_add_subregion(&s->container, IOSCB_LANE23_BASE, &s->lane23);
 162
 163    memory_region_init_io(&s->ctrl, OBJECT(s), &mchp_pfsoc_dummy_ops, s,
 164                          "mchp.pfsoc.ioscb.ctrl", IOSCB_SUBMOD_REG_SIZE);
 165    memory_region_add_subregion(&s->container, IOSCB_CTRL_BASE, &s->ctrl);
 166
 167    memory_region_init_io(&s->cfg, OBJECT(s), &mchp_pfsoc_dummy_ops, s,
 168                          "mchp.pfsoc.ioscb.cfg", IOSCB_SUBMOD_REG_SIZE);
 169    memory_region_add_subregion(&s->container, IOSCB_CFG_BASE, &s->cfg);
 170
 171    memory_region_init_io(&s->pll_mss, OBJECT(s), &mchp_pfsoc_pll_ops, s,
 172                          "mchp.pfsoc.ioscb.pll_mss", IOSCB_SUBMOD_REG_SIZE);
 173    memory_region_add_subregion(&s->container, IOSCB_PLL_MSS_BASE, &s->pll_mss);
 174
 175    memory_region_init_io(&s->cfm_mss, OBJECT(s), &mchp_pfsoc_dummy_ops, s,
 176                          "mchp.pfsoc.ioscb.cfm_mss", IOSCB_SUBMOD_REG_SIZE);
 177    memory_region_add_subregion(&s->container, IOSCB_CFM_MSS_BASE, &s->cfm_mss);
 178
 179    memory_region_init_io(&s->pll_ddr, OBJECT(s), &mchp_pfsoc_pll_ops, s,
 180                          "mchp.pfsoc.ioscb.pll_ddr", IOSCB_SUBMOD_REG_SIZE);
 181    memory_region_add_subregion(&s->container, IOSCB_PLL_DDR_BASE, &s->pll_ddr);
 182
 183    memory_region_init_io(&s->bc_ddr, OBJECT(s), &mchp_pfsoc_dummy_ops, s,
 184                          "mchp.pfsoc.ioscb.bc_ddr", IOSCB_SUBMOD_REG_SIZE);
 185    memory_region_add_subregion(&s->container, IOSCB_BC_DDR_BASE, &s->bc_ddr);
 186
 187    memory_region_init_io(&s->io_calib_ddr, OBJECT(s),
 188                          &mchp_pfsoc_io_calib_ddr_ops, s,
 189                          "mchp.pfsoc.ioscb.io_calib_ddr",
 190                          IOSCB_SUBMOD_REG_SIZE);
 191    memory_region_add_subregion(&s->container, IOSCB_IO_CALIB_DDR_BASE,
 192                                &s->io_calib_ddr);
 193
 194    memory_region_init_io(&s->pll_sgmii, OBJECT(s), &mchp_pfsoc_pll_ops, s,
 195                          "mchp.pfsoc.ioscb.pll_sgmii", IOSCB_SUBMOD_REG_SIZE);
 196    memory_region_add_subregion(&s->container, IOSCB_PLL_SGMII_BASE,
 197                                &s->pll_sgmii);
 198
 199    memory_region_init_io(&s->dll_sgmii, OBJECT(s), &mchp_pfsoc_dummy_ops, s,
 200                          "mchp.pfsoc.ioscb.dll_sgmii", IOSCB_SUBMOD_REG_SIZE);
 201    memory_region_add_subregion(&s->container, IOSCB_DLL_SGMII_BASE,
 202                                &s->dll_sgmii);
 203
 204    memory_region_init_io(&s->cfm_sgmii, OBJECT(s), &mchp_pfsoc_dummy_ops, s,
 205                          "mchp.pfsoc.ioscb.cfm_sgmii", IOSCB_SUBMOD_REG_SIZE);
 206    memory_region_add_subregion(&s->container, IOSCB_CFM_SGMII_BASE,
 207                                &s->cfm_sgmii);
 208
 209    memory_region_init_io(&s->bc_sgmii, OBJECT(s), &mchp_pfsoc_dummy_ops, s,
 210                          "mchp.pfsoc.ioscb.bc_sgmii", IOSCB_SUBMOD_REG_SIZE);
 211    memory_region_add_subregion(&s->container, IOSCB_BC_SGMII_BASE,
 212                                &s->bc_sgmii);
 213
 214    memory_region_init_io(&s->io_calib_sgmii, OBJECT(s), &mchp_pfsoc_dummy_ops,
 215                          s, "mchp.pfsoc.ioscb.io_calib_sgmii",
 216                          IOSCB_SUBMOD_REG_SIZE);
 217    memory_region_add_subregion(&s->container, IOSCB_IO_CALIB_SGMII_BASE,
 218                                &s->io_calib_sgmii);
 219}
 220
 221static void mchp_pfsoc_ioscb_class_init(ObjectClass *klass, void *data)
 222{
 223    DeviceClass *dc = DEVICE_CLASS(klass);
 224
 225    dc->desc = "Microchip PolarFire SoC IOSCB modules";
 226    dc->realize = mchp_pfsoc_ioscb_realize;
 227}
 228
 229static const TypeInfo mchp_pfsoc_ioscb_info = {
 230    .name          = TYPE_MCHP_PFSOC_IOSCB,
 231    .parent        = TYPE_SYS_BUS_DEVICE,
 232    .instance_size = sizeof(MchpPfSoCIoscbState),
 233    .class_init    = mchp_pfsoc_ioscb_class_init,
 234};
 235
 236static void mchp_pfsoc_ioscb_register_types(void)
 237{
 238    type_register_static(&mchp_pfsoc_ioscb_info);
 239}
 240
 241type_init(mchp_pfsoc_ioscb_register_types)
 242