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