2 * Microchip PolarFire SoC DDR Memory Controller module emulation
4 * Copyright (c) 2020 Wind River Systems, Inc.
7 * Bin Meng <bin.meng@windriver.com>
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.
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.
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/>.
23 #include "qemu/osdep.h"
24 #include "qemu/bitops.h"
26 #include "qapi/error.h"
28 #include "hw/sysbus.h"
29 #include "hw/misc/mchp_pfsoc_dmc.h"
31 /* DDR SGMII PHY module */
33 #define SGMII_PHY_IOC_REG1 0x208
34 #define SGMII_PHY_TRAINING_STATUS 0x814
35 #define SGMII_PHY_DQ_DQS_ERR_DONE 0x834
36 #define SGMII_PHY_DQDQS_STATUS1 0x84c
37 #define SGMII_PHY_PVT_STAT 0xc20
39 static uint64_t mchp_pfsoc_ddr_sgmii_phy_read(void *opaque
, hwaddr offset
,
43 static int training_status_bit
;
46 case SGMII_PHY_IOC_REG1
:
47 /* See ddr_pvt_calibration() in HSS */
48 val
= BIT(4) | BIT(2);
50 case SGMII_PHY_TRAINING_STATUS
:
52 * The codes logic emulates the training status change from
53 * DDR_TRAINING_IP_SM_BCLKSCLK to DDR_TRAINING_IP_SM_DQ_DQS.
55 * See ddr_setup() in mss_ddr.c in the HSS source codes.
57 val
= 1 << training_status_bit
;
58 training_status_bit
= (training_status_bit
+ 1) % 5;
60 case SGMII_PHY_DQ_DQS_ERR_DONE
:
62 * DDR_TRAINING_IP_SM_VERIFY state in ddr_setup(),
63 * check that DQ/DQS training passed without error.
67 case SGMII_PHY_DQDQS_STATUS1
:
69 * DDR_TRAINING_IP_SM_VERIFY state in ddr_setup(),
70 * check that DQ/DQS calculated window is above 5 taps.
74 case SGMII_PHY_PVT_STAT
:
75 /* See sgmii_channel_setup() in HSS */
76 val
= BIT(14) | BIT(6);
79 qemu_log_mask(LOG_UNIMP
, "%s: unimplemented device read "
80 "(size %d, offset 0x%" HWADDR_PRIx
")\n",
81 __func__
, size
, offset
);
88 static void mchp_pfsoc_ddr_sgmii_phy_write(void *opaque
, hwaddr offset
,
89 uint64_t value
, unsigned size
)
91 qemu_log_mask(LOG_UNIMP
, "%s: unimplemented device write "
92 "(size %d, value 0x%" PRIx64
93 ", offset 0x%" HWADDR_PRIx
")\n",
94 __func__
, size
, value
, offset
);
97 static const MemoryRegionOps mchp_pfsoc_ddr_sgmii_phy_ops
= {
98 .read
= mchp_pfsoc_ddr_sgmii_phy_read
,
99 .write
= mchp_pfsoc_ddr_sgmii_phy_write
,
100 .endianness
= DEVICE_LITTLE_ENDIAN
,
103 static void mchp_pfsoc_ddr_sgmii_phy_realize(DeviceState
*dev
, Error
**errp
)
105 MchpPfSoCDdrSgmiiPhyState
*s
= MCHP_PFSOC_DDR_SGMII_PHY(dev
);
107 memory_region_init_io(&s
->sgmii_phy
, OBJECT(dev
),
108 &mchp_pfsoc_ddr_sgmii_phy_ops
, s
,
109 "mchp.pfsoc.ddr_sgmii_phy",
110 MCHP_PFSOC_DDR_SGMII_PHY_REG_SIZE
);
111 sysbus_init_mmio(SYS_BUS_DEVICE(dev
), &s
->sgmii_phy
);
114 static void mchp_pfsoc_ddr_sgmii_phy_class_init(ObjectClass
*klass
, void *data
)
116 DeviceClass
*dc
= DEVICE_CLASS(klass
);
118 dc
->desc
= "Microchip PolarFire SoC DDR SGMII PHY module";
119 dc
->realize
= mchp_pfsoc_ddr_sgmii_phy_realize
;
122 static const TypeInfo mchp_pfsoc_ddr_sgmii_phy_info
= {
123 .name
= TYPE_MCHP_PFSOC_DDR_SGMII_PHY
,
124 .parent
= TYPE_SYS_BUS_DEVICE
,
125 .instance_size
= sizeof(MchpPfSoCDdrSgmiiPhyState
),
126 .class_init
= mchp_pfsoc_ddr_sgmii_phy_class_init
,
129 static void mchp_pfsoc_ddr_sgmii_phy_register_types(void)
131 type_register_static(&mchp_pfsoc_ddr_sgmii_phy_info
);
134 type_init(mchp_pfsoc_ddr_sgmii_phy_register_types
)
138 #define CFG_MT_DONE_ACK 0x4428
139 #define CFG_STAT_DFI_INIT_COMPLETE 0x10034
140 #define CFG_STAT_DFI_TRAINING_COMPLETE 0x10038
142 static uint64_t mchp_pfsoc_ddr_cfg_read(void *opaque
, hwaddr offset
,
148 case CFG_MT_DONE_ACK
:
149 /* memory test in MTC_test() */
152 case CFG_STAT_DFI_INIT_COMPLETE
:
153 /* DDR_TRAINING_IP_SM_START_CHECK state in ddr_setup() */
156 case CFG_STAT_DFI_TRAINING_COMPLETE
:
157 /* DDR_TRAINING_IP_SM_VERIFY state in ddr_setup() */
161 qemu_log_mask(LOG_UNIMP
, "%s: unimplemented device read "
162 "(size %d, offset 0x%" HWADDR_PRIx
")\n",
163 __func__
, size
, offset
);
170 static void mchp_pfsoc_ddr_cfg_write(void *opaque
, hwaddr offset
,
171 uint64_t value
, unsigned size
)
173 qemu_log_mask(LOG_UNIMP
, "%s: unimplemented device write "
174 "(size %d, value 0x%" PRIx64
175 ", offset 0x%" HWADDR_PRIx
")\n",
176 __func__
, size
, value
, offset
);
179 static const MemoryRegionOps mchp_pfsoc_ddr_cfg_ops
= {
180 .read
= mchp_pfsoc_ddr_cfg_read
,
181 .write
= mchp_pfsoc_ddr_cfg_write
,
182 .endianness
= DEVICE_LITTLE_ENDIAN
,
185 static void mchp_pfsoc_ddr_cfg_realize(DeviceState
*dev
, Error
**errp
)
187 MchpPfSoCDdrCfgState
*s
= MCHP_PFSOC_DDR_CFG(dev
);
189 memory_region_init_io(&s
->cfg
, OBJECT(dev
),
190 &mchp_pfsoc_ddr_cfg_ops
, s
,
191 "mchp.pfsoc.ddr_cfg",
192 MCHP_PFSOC_DDR_CFG_REG_SIZE
);
193 sysbus_init_mmio(SYS_BUS_DEVICE(dev
), &s
->cfg
);
196 static void mchp_pfsoc_ddr_cfg_class_init(ObjectClass
*klass
, void *data
)
198 DeviceClass
*dc
= DEVICE_CLASS(klass
);
200 dc
->desc
= "Microchip PolarFire SoC DDR CFG module";
201 dc
->realize
= mchp_pfsoc_ddr_cfg_realize
;
204 static const TypeInfo mchp_pfsoc_ddr_cfg_info
= {
205 .name
= TYPE_MCHP_PFSOC_DDR_CFG
,
206 .parent
= TYPE_SYS_BUS_DEVICE
,
207 .instance_size
= sizeof(MchpPfSoCDdrCfgState
),
208 .class_init
= mchp_pfsoc_ddr_cfg_class_init
,
211 static void mchp_pfsoc_ddr_cfg_register_types(void)
213 type_register_static(&mchp_pfsoc_ddr_cfg_info
);
216 type_init(mchp_pfsoc_ddr_cfg_register_types
)