1 /*
2 * i.MX8 PCIe PHY emulation
3 *
4 * Copyright (c) 2025 Bernhard Beschow <shentey@gmail.com>
5 *
6 * SPDX-License-Identifier: GPL-2.0-or-later
7 */
8
9 #include "qemu/osdep.h"
10 #include "hw/pci-host/fsl_imx8m_phy.h"
11 #include "hw/resettable.h"
12 #include "migration/vmstate.h"
13
14 #define CMN_REG075 0x1d4
15 #define ANA_PLL_LOCK_DONE BIT(1)
16 #define ANA_PLL_AFC_DONE BIT(0)
17
fsl_imx8m_pcie_phy_read(void * opaque,hwaddr offset,unsigned size)18 static uint64_t fsl_imx8m_pcie_phy_read(void *opaque, hwaddr offset,
19 unsigned size)
20 {
21 FslImx8mPciePhyState *s = opaque;
22
23 if (offset == CMN_REG075) {
24 return s->data[offset] | ANA_PLL_LOCK_DONE | ANA_PLL_AFC_DONE;
25 }
26
27 return s->data[offset];
28 }
29
fsl_imx8m_pcie_phy_write(void * opaque,hwaddr offset,uint64_t value,unsigned size)30 static void fsl_imx8m_pcie_phy_write(void *opaque, hwaddr offset,
31 uint64_t value, unsigned size)
32 {
33 FslImx8mPciePhyState *s = opaque;
34
35 s->data[offset] = value;
36 }
37
38 static const MemoryRegionOps fsl_imx8m_pcie_phy_ops = {
39 .read = fsl_imx8m_pcie_phy_read,
40 .write = fsl_imx8m_pcie_phy_write,
41 .impl = {
42 .min_access_size = 1,
43 .max_access_size = 1,
44 },
45 .valid = {
46 .min_access_size = 1,
47 .max_access_size = 8,
48 },
49 .endianness = DEVICE_LITTLE_ENDIAN,
50 };
51
fsl_imx8m_pcie_phy_realize(DeviceState * dev,Error ** errp)52 static void fsl_imx8m_pcie_phy_realize(DeviceState *dev, Error **errp)
53 {
54 FslImx8mPciePhyState *s = FSL_IMX8M_PCIE_PHY(dev);
55
56 memory_region_init_io(&s->iomem, OBJECT(s), &fsl_imx8m_pcie_phy_ops, s,
57 TYPE_FSL_IMX8M_PCIE_PHY, ARRAY_SIZE(s->data));
58 sysbus_init_mmio(SYS_BUS_DEVICE(s), &s->iomem);
59 }
60
fsl_imx8m_pcie_phy_reset_hold(Object * obj,ResetType type)61 static void fsl_imx8m_pcie_phy_reset_hold(Object *obj, ResetType type)
62 {
63 FslImx8mPciePhyState *s = FSL_IMX8M_PCIE_PHY(obj);
64
65 memset(s->data, 0, sizeof(s->data));
66 }
67
68 static const VMStateDescription fsl_imx8m_pcie_phy_vmstate = {
69 .name = "fsl-imx8m-pcie-phy",
70 .version_id = 1,
71 .minimum_version_id = 1,
72 .fields = (const VMStateField[]) {
73 VMSTATE_UINT8_ARRAY(data, FslImx8mPciePhyState,
74 FSL_IMX8M_PCIE_PHY_DATA_SIZE),
75 VMSTATE_END_OF_LIST()
76 }
77 };
78
fsl_imx8m_pcie_phy_class_init(ObjectClass * klass,const void * data)79 static void fsl_imx8m_pcie_phy_class_init(ObjectClass *klass, const void *data)
80 {
81 DeviceClass *dc = DEVICE_CLASS(klass);
82 ResettableClass *rc = RESETTABLE_CLASS(klass);
83
84 dc->realize = fsl_imx8m_pcie_phy_realize;
85 dc->vmsd = &fsl_imx8m_pcie_phy_vmstate;
86 rc->phases.hold = fsl_imx8m_pcie_phy_reset_hold;
87 }
88
89 static const TypeInfo fsl_imx8m_pcie_phy_types[] = {
90 {
91 .name = TYPE_FSL_IMX8M_PCIE_PHY,
92 .parent = TYPE_SYS_BUS_DEVICE,
93 .instance_size = sizeof(FslImx8mPciePhyState),
94 .class_init = fsl_imx8m_pcie_phy_class_init,
95 }
96 };
97
98 DEFINE_TYPES(fsl_imx8m_pcie_phy_types)
99