xref: /qemu/hw/pci-host/fsl_imx8m_phy.c (revision 6ff5da16000f908140723e164d33a0b51a6c4162)
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 
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 
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 
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 
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 
79 static void fsl_imx8m_pcie_phy_class_init(ObjectClass *klass, 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