1a937b302SBin Meng /* 2a937b302SBin Meng * Microchip PolarFire SoC IOSCB module emulation 3a937b302SBin Meng * 4a937b302SBin Meng * Copyright (c) 2020 Wind River Systems, Inc. 5a937b302SBin Meng * 6a937b302SBin Meng * Author: 7a937b302SBin Meng * Bin Meng <bin.meng@windriver.com> 8a937b302SBin Meng * 9a937b302SBin Meng * This program is free software; you can redistribute it and/or 10a937b302SBin Meng * modify it under the terms of the GNU General Public License as 11a937b302SBin Meng * published by the Free Software Foundation; either version 2 or 12a937b302SBin Meng * (at your option) version 3 of the License. 13a937b302SBin Meng * 14a937b302SBin Meng * This program is distributed in the hope that it will be useful, 15a937b302SBin Meng * but WITHOUT ANY WARRANTY; without even the implied warranty of 16a937b302SBin Meng * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17a937b302SBin Meng * GNU General Public License for more details. 18a937b302SBin Meng * 19a937b302SBin Meng * You should have received a copy of the GNU General Public License along 20a937b302SBin Meng * with this program; if not, see <http://www.gnu.org/licenses/>. 21a937b302SBin Meng */ 22a937b302SBin Meng 23a937b302SBin Meng #include "qemu/osdep.h" 24a937b302SBin Meng #include "qemu/bitops.h" 25a937b302SBin Meng #include "qemu/log.h" 26a937b302SBin Meng #include "qapi/error.h" 27a937b302SBin Meng #include "hw/sysbus.h" 28a937b302SBin Meng #include "hw/misc/mchp_pfsoc_ioscb.h" 29a937b302SBin Meng 30a937b302SBin Meng /* 31a937b302SBin Meng * The whole IOSCB module registers map into the system address at 0x3000_0000, 32a937b302SBin Meng * named as "System Port 0 (AXI-D0)". 33a937b302SBin Meng */ 34a937b302SBin Meng #define IOSCB_WHOLE_REG_SIZE 0x10000000 35a937b302SBin Meng #define IOSCB_SUBMOD_REG_SIZE 0x1000 36*13cd1d6eSConor Dooley #define IOSCB_CCC_REG_SIZE 0x2000000 37a937b302SBin Meng 38a937b302SBin Meng /* 39a937b302SBin Meng * There are many sub-modules in the IOSCB module. 40a937b302SBin Meng * See Microchip PolarFire SoC documentation (Register_Map.zip), 41a937b302SBin Meng * Register Map/PF_SoC_RegMap_V1_1/MPFS250T/mpfs250t_ioscb_memmap_dri.htm 42a937b302SBin Meng * 43a937b302SBin Meng * The following are sub-modules offsets that are of concern. 44a937b302SBin Meng */ 45a937b302SBin Meng #define IOSCB_LANE01_BASE 0x06500000 46a937b302SBin Meng #define IOSCB_LANE23_BASE 0x06510000 47a937b302SBin Meng #define IOSCB_CTRL_BASE 0x07020000 48a937b302SBin Meng #define IOSCB_CFG_BASE 0x07080000 49*13cd1d6eSConor Dooley #define IOSCB_CCC_BASE 0x08000000 50a937b302SBin Meng #define IOSCB_PLL_MSS_BASE 0x0E001000 51a937b302SBin Meng #define IOSCB_CFM_MSS_BASE 0x0E002000 52a937b302SBin Meng #define IOSCB_PLL_DDR_BASE 0x0E010000 53a937b302SBin Meng #define IOSCB_BC_DDR_BASE 0x0E020000 54a937b302SBin Meng #define IOSCB_IO_CALIB_DDR_BASE 0x0E040000 55a937b302SBin Meng #define IOSCB_PLL_SGMII_BASE 0x0E080000 56a937b302SBin Meng #define IOSCB_DLL_SGMII_BASE 0x0E100000 57a937b302SBin Meng #define IOSCB_CFM_SGMII_BASE 0x0E200000 58a937b302SBin Meng #define IOSCB_BC_SGMII_BASE 0x0E400000 59a937b302SBin Meng #define IOSCB_IO_CALIB_SGMII_BASE 0x0E800000 60a937b302SBin Meng 61a937b302SBin Meng static uint64_t mchp_pfsoc_dummy_read(void *opaque, hwaddr offset, 62a937b302SBin Meng unsigned size) 63a937b302SBin Meng { 64a937b302SBin Meng qemu_log_mask(LOG_UNIMP, "%s: unimplemented device read " 65a937b302SBin Meng "(size %d, offset 0x%" HWADDR_PRIx ")\n", 66a937b302SBin Meng __func__, size, offset); 67a937b302SBin Meng 68a937b302SBin Meng return 0; 69a937b302SBin Meng } 70a937b302SBin Meng 71a937b302SBin Meng static void mchp_pfsoc_dummy_write(void *opaque, hwaddr offset, 72a937b302SBin Meng uint64_t value, unsigned size) 73a937b302SBin Meng { 74a937b302SBin Meng qemu_log_mask(LOG_UNIMP, "%s: unimplemented device write " 75a937b302SBin Meng "(size %d, value 0x%" PRIx64 76a937b302SBin Meng ", offset 0x%" HWADDR_PRIx ")\n", 77a937b302SBin Meng __func__, size, value, offset); 78a937b302SBin Meng } 79a937b302SBin Meng 80a937b302SBin Meng static const MemoryRegionOps mchp_pfsoc_dummy_ops = { 81a937b302SBin Meng .read = mchp_pfsoc_dummy_read, 82a937b302SBin Meng .write = mchp_pfsoc_dummy_write, 83a937b302SBin Meng .endianness = DEVICE_LITTLE_ENDIAN, 84a937b302SBin Meng }; 85a937b302SBin Meng 86a937b302SBin Meng /* All PLL modules in IOSCB have the same register layout */ 87a937b302SBin Meng 88a937b302SBin Meng #define PLL_CTRL 0x04 89a937b302SBin Meng 90a937b302SBin Meng static uint64_t mchp_pfsoc_pll_read(void *opaque, hwaddr offset, 91a937b302SBin Meng unsigned size) 92a937b302SBin Meng { 93a937b302SBin Meng uint32_t val = 0; 94a937b302SBin Meng 95a937b302SBin Meng switch (offset) { 96a937b302SBin Meng case PLL_CTRL: 97a937b302SBin Meng /* PLL is locked */ 98a937b302SBin Meng val = BIT(25); 99a937b302SBin Meng break; 100a937b302SBin Meng default: 101a937b302SBin Meng qemu_log_mask(LOG_UNIMP, "%s: unimplemented device read " 102a937b302SBin Meng "(size %d, offset 0x%" HWADDR_PRIx ")\n", 103a937b302SBin Meng __func__, size, offset); 104a937b302SBin Meng break; 105a937b302SBin Meng } 106a937b302SBin Meng 107a937b302SBin Meng return val; 108a937b302SBin Meng } 109a937b302SBin Meng 110a937b302SBin Meng static const MemoryRegionOps mchp_pfsoc_pll_ops = { 111a937b302SBin Meng .read = mchp_pfsoc_pll_read, 112a937b302SBin Meng .write = mchp_pfsoc_dummy_write, 113a937b302SBin Meng .endianness = DEVICE_LITTLE_ENDIAN, 114a937b302SBin Meng }; 115a937b302SBin Meng 116a937b302SBin Meng /* IO_CALIB_DDR submodule */ 117a937b302SBin Meng 118a937b302SBin Meng #define IO_CALIB_DDR_IOC_REG1 0x08 119a937b302SBin Meng 120a937b302SBin Meng static uint64_t mchp_pfsoc_io_calib_ddr_read(void *opaque, hwaddr offset, 121a937b302SBin Meng unsigned size) 122a937b302SBin Meng { 123a937b302SBin Meng uint32_t val = 0; 124a937b302SBin Meng 125a937b302SBin Meng switch (offset) { 126a937b302SBin Meng case IO_CALIB_DDR_IOC_REG1: 127a937b302SBin Meng /* calibration completed */ 128a937b302SBin Meng val = BIT(2); 129a937b302SBin Meng break; 130a937b302SBin Meng default: 131a937b302SBin Meng qemu_log_mask(LOG_UNIMP, "%s: unimplemented device read " 132a937b302SBin Meng "(size %d, offset 0x%" HWADDR_PRIx ")\n", 133a937b302SBin Meng __func__, size, offset); 134a937b302SBin Meng break; 135a937b302SBin Meng } 136a937b302SBin Meng 137a937b302SBin Meng return val; 138a937b302SBin Meng } 139a937b302SBin Meng 140a937b302SBin Meng static const MemoryRegionOps mchp_pfsoc_io_calib_ddr_ops = { 141a937b302SBin Meng .read = mchp_pfsoc_io_calib_ddr_read, 142a937b302SBin Meng .write = mchp_pfsoc_dummy_write, 143a937b302SBin Meng .endianness = DEVICE_LITTLE_ENDIAN, 144a937b302SBin Meng }; 145a937b302SBin Meng 146a937b302SBin Meng static void mchp_pfsoc_ioscb_realize(DeviceState *dev, Error **errp) 147a937b302SBin Meng { 148a937b302SBin Meng MchpPfSoCIoscbState *s = MCHP_PFSOC_IOSCB(dev); 149a937b302SBin Meng SysBusDevice *sbd = SYS_BUS_DEVICE(dev); 150a937b302SBin Meng 151a937b302SBin Meng memory_region_init(&s->container, OBJECT(s), 152a937b302SBin Meng "mchp.pfsoc.ioscb", IOSCB_WHOLE_REG_SIZE); 153a937b302SBin Meng sysbus_init_mmio(sbd, &s->container); 154a937b302SBin Meng 155a937b302SBin Meng /* add subregions for all sub-modules in IOSCB */ 156a937b302SBin Meng 157a937b302SBin Meng memory_region_init_io(&s->lane01, OBJECT(s), &mchp_pfsoc_dummy_ops, s, 158a937b302SBin Meng "mchp.pfsoc.ioscb.lane01", IOSCB_SUBMOD_REG_SIZE); 159a937b302SBin Meng memory_region_add_subregion(&s->container, IOSCB_LANE01_BASE, &s->lane01); 160a937b302SBin Meng 161a937b302SBin Meng memory_region_init_io(&s->lane23, OBJECT(s), &mchp_pfsoc_dummy_ops, s, 162a937b302SBin Meng "mchp.pfsoc.ioscb.lane23", IOSCB_SUBMOD_REG_SIZE); 163a937b302SBin Meng memory_region_add_subregion(&s->container, IOSCB_LANE23_BASE, &s->lane23); 164a937b302SBin Meng 165a937b302SBin Meng memory_region_init_io(&s->ctrl, OBJECT(s), &mchp_pfsoc_dummy_ops, s, 166a937b302SBin Meng "mchp.pfsoc.ioscb.ctrl", IOSCB_SUBMOD_REG_SIZE); 167a937b302SBin Meng memory_region_add_subregion(&s->container, IOSCB_CTRL_BASE, &s->ctrl); 168a937b302SBin Meng 169a937b302SBin Meng memory_region_init_io(&s->cfg, OBJECT(s), &mchp_pfsoc_dummy_ops, s, 170a937b302SBin Meng "mchp.pfsoc.ioscb.cfg", IOSCB_SUBMOD_REG_SIZE); 171a937b302SBin Meng memory_region_add_subregion(&s->container, IOSCB_CFG_BASE, &s->cfg); 172a937b302SBin Meng 173*13cd1d6eSConor Dooley memory_region_init_io(&s->ccc, OBJECT(s), &mchp_pfsoc_dummy_ops, s, 174*13cd1d6eSConor Dooley "mchp.pfsoc.ioscb.ccc", IOSCB_CCC_REG_SIZE); 175*13cd1d6eSConor Dooley memory_region_add_subregion(&s->container, IOSCB_CCC_BASE, &s->ccc); 176*13cd1d6eSConor Dooley 177a937b302SBin Meng memory_region_init_io(&s->pll_mss, OBJECT(s), &mchp_pfsoc_pll_ops, s, 178a937b302SBin Meng "mchp.pfsoc.ioscb.pll_mss", IOSCB_SUBMOD_REG_SIZE); 179a937b302SBin Meng memory_region_add_subregion(&s->container, IOSCB_PLL_MSS_BASE, &s->pll_mss); 180a937b302SBin Meng 181a937b302SBin Meng memory_region_init_io(&s->cfm_mss, OBJECT(s), &mchp_pfsoc_dummy_ops, s, 182a937b302SBin Meng "mchp.pfsoc.ioscb.cfm_mss", IOSCB_SUBMOD_REG_SIZE); 183a937b302SBin Meng memory_region_add_subregion(&s->container, IOSCB_CFM_MSS_BASE, &s->cfm_mss); 184a937b302SBin Meng 185a937b302SBin Meng memory_region_init_io(&s->pll_ddr, OBJECT(s), &mchp_pfsoc_pll_ops, s, 186a937b302SBin Meng "mchp.pfsoc.ioscb.pll_ddr", IOSCB_SUBMOD_REG_SIZE); 187a937b302SBin Meng memory_region_add_subregion(&s->container, IOSCB_PLL_DDR_BASE, &s->pll_ddr); 188a937b302SBin Meng 189a937b302SBin Meng memory_region_init_io(&s->bc_ddr, OBJECT(s), &mchp_pfsoc_dummy_ops, s, 190a937b302SBin Meng "mchp.pfsoc.ioscb.bc_ddr", IOSCB_SUBMOD_REG_SIZE); 191a937b302SBin Meng memory_region_add_subregion(&s->container, IOSCB_BC_DDR_BASE, &s->bc_ddr); 192a937b302SBin Meng 193a937b302SBin Meng memory_region_init_io(&s->io_calib_ddr, OBJECT(s), 194a937b302SBin Meng &mchp_pfsoc_io_calib_ddr_ops, s, 195a937b302SBin Meng "mchp.pfsoc.ioscb.io_calib_ddr", 196a937b302SBin Meng IOSCB_SUBMOD_REG_SIZE); 197a937b302SBin Meng memory_region_add_subregion(&s->container, IOSCB_IO_CALIB_DDR_BASE, 198a937b302SBin Meng &s->io_calib_ddr); 199a937b302SBin Meng 200a937b302SBin Meng memory_region_init_io(&s->pll_sgmii, OBJECT(s), &mchp_pfsoc_pll_ops, s, 201a937b302SBin Meng "mchp.pfsoc.ioscb.pll_sgmii", IOSCB_SUBMOD_REG_SIZE); 202a937b302SBin Meng memory_region_add_subregion(&s->container, IOSCB_PLL_SGMII_BASE, 203a937b302SBin Meng &s->pll_sgmii); 204a937b302SBin Meng 205a937b302SBin Meng memory_region_init_io(&s->dll_sgmii, OBJECT(s), &mchp_pfsoc_dummy_ops, s, 206a937b302SBin Meng "mchp.pfsoc.ioscb.dll_sgmii", IOSCB_SUBMOD_REG_SIZE); 207a937b302SBin Meng memory_region_add_subregion(&s->container, IOSCB_DLL_SGMII_BASE, 208a937b302SBin Meng &s->dll_sgmii); 209a937b302SBin Meng 210a937b302SBin Meng memory_region_init_io(&s->cfm_sgmii, OBJECT(s), &mchp_pfsoc_dummy_ops, s, 211a937b302SBin Meng "mchp.pfsoc.ioscb.cfm_sgmii", IOSCB_SUBMOD_REG_SIZE); 212a937b302SBin Meng memory_region_add_subregion(&s->container, IOSCB_CFM_SGMII_BASE, 213a937b302SBin Meng &s->cfm_sgmii); 214a937b302SBin Meng 215a937b302SBin Meng memory_region_init_io(&s->bc_sgmii, OBJECT(s), &mchp_pfsoc_dummy_ops, s, 216a937b302SBin Meng "mchp.pfsoc.ioscb.bc_sgmii", IOSCB_SUBMOD_REG_SIZE); 217a937b302SBin Meng memory_region_add_subregion(&s->container, IOSCB_BC_SGMII_BASE, 218a937b302SBin Meng &s->bc_sgmii); 219a937b302SBin Meng 220a937b302SBin Meng memory_region_init_io(&s->io_calib_sgmii, OBJECT(s), &mchp_pfsoc_dummy_ops, 221a937b302SBin Meng s, "mchp.pfsoc.ioscb.io_calib_sgmii", 222a937b302SBin Meng IOSCB_SUBMOD_REG_SIZE); 223a937b302SBin Meng memory_region_add_subregion(&s->container, IOSCB_IO_CALIB_SGMII_BASE, 224a937b302SBin Meng &s->io_calib_sgmii); 225a937b302SBin Meng } 226a937b302SBin Meng 227a937b302SBin Meng static void mchp_pfsoc_ioscb_class_init(ObjectClass *klass, void *data) 228a937b302SBin Meng { 229a937b302SBin Meng DeviceClass *dc = DEVICE_CLASS(klass); 230a937b302SBin Meng 231a937b302SBin Meng dc->desc = "Microchip PolarFire SoC IOSCB modules"; 232a937b302SBin Meng dc->realize = mchp_pfsoc_ioscb_realize; 233a937b302SBin Meng } 234a937b302SBin Meng 235a937b302SBin Meng static const TypeInfo mchp_pfsoc_ioscb_info = { 236a937b302SBin Meng .name = TYPE_MCHP_PFSOC_IOSCB, 237a937b302SBin Meng .parent = TYPE_SYS_BUS_DEVICE, 238a937b302SBin Meng .instance_size = sizeof(MchpPfSoCIoscbState), 239a937b302SBin Meng .class_init = mchp_pfsoc_ioscb_class_init, 240a937b302SBin Meng }; 241a937b302SBin Meng 242a937b302SBin Meng static void mchp_pfsoc_ioscb_register_types(void) 243a937b302SBin Meng { 244a937b302SBin Meng type_register_static(&mchp_pfsoc_ioscb_info); 245a937b302SBin Meng } 246a937b302SBin Meng 247a937b302SBin Meng type_init(mchp_pfsoc_ioscb_register_types) 248