4 * Copyright (c) 2020 Guenter Roeck <linux@roeck-us.net>
6 * This work is licensed under the terms of the GNU GPL, version 2 or later.
7 * See the COPYING file in the top-level directory.
9 * We need to implement basic reset control in the PHY control register.
10 * For everything else, it is sufficient to set whatever is written.
13 #include "qemu/osdep.h"
14 #include "hw/usb/imx-usb-phy.h"
15 #include "migration/vmstate.h"
16 #include "qemu/module.h"
18 static const VMStateDescription vmstate_imx_usbphy
= {
19 .name
= TYPE_IMX_USBPHY
,
21 .minimum_version_id
= 1,
22 .fields
= (VMStateField
[]) {
23 VMSTATE_UINT32_ARRAY(usbphy
, IMXUSBPHYState
, USBPHY_MAX
),
28 static void imx_usbphy_softreset(IMXUSBPHYState
*s
)
30 s
->usbphy
[USBPHY_PWD
] = 0x001e1c00;
31 s
->usbphy
[USBPHY_TX
] = 0x10060607;
32 s
->usbphy
[USBPHY_RX
] = 0x00000000;
33 s
->usbphy
[USBPHY_CTRL
] = 0xc0200000;
36 static void imx_usbphy_reset(DeviceState
*dev
)
38 IMXUSBPHYState
*s
= IMX_USBPHY(dev
);
40 s
->usbphy
[USBPHY_STATUS
] = 0x00000000;
41 s
->usbphy
[USBPHY_DEBUG
] = 0x7f180000;
42 s
->usbphy
[USBPHY_DEBUG0_STATUS
] = 0x00000000;
43 s
->usbphy
[USBPHY_DEBUG1
] = 0x00001000;
44 s
->usbphy
[USBPHY_VERSION
] = 0x04020000;
46 imx_usbphy_softreset(s
);
49 static uint64_t imx_usbphy_read(void *opaque
, hwaddr offset
, unsigned size
)
51 IMXUSBPHYState
*s
= (IMXUSBPHYState
*)opaque
;
52 uint32_t index
= offset
>> 2;
60 case USBPHY_DEBUG_SET
:
61 case USBPHY_DEBUG1_SET
:
63 * All REG_NAME_SET register access are in fact targeting the
66 value
= s
->usbphy
[index
- 1];
72 case USBPHY_DEBUG_CLR
:
73 case USBPHY_DEBUG1_CLR
:
75 * All REG_NAME_CLR register access are in fact targeting the
78 value
= s
->usbphy
[index
- 2];
84 case USBPHY_DEBUG_TOG
:
85 case USBPHY_DEBUG1_TOG
:
87 * All REG_NAME_TOG register access are in fact targeting the
90 value
= s
->usbphy
[index
- 3];
93 value
= s
->usbphy
[index
];
96 return (uint64_t)value
;
99 static void imx_usbphy_write(void *opaque
, hwaddr offset
, uint64_t value
,
102 IMXUSBPHYState
*s
= (IMXUSBPHYState
*)opaque
;
103 uint32_t index
= offset
>> 2;
107 s
->usbphy
[index
] = value
;
108 if (value
& USBPHY_CTRL_SFTRST
) {
109 imx_usbphy_softreset(s
);
118 s
->usbphy
[index
] = value
;
120 case USBPHY_CTRL_SET
:
121 s
->usbphy
[index
- 1] |= value
;
122 if (value
& USBPHY_CTRL_SFTRST
) {
123 imx_usbphy_softreset(s
);
129 case USBPHY_DEBUG_SET
:
130 case USBPHY_DEBUG1_SET
:
132 * All REG_NAME_SET register access are in fact targeting the
133 * REG_NAME register. So we change the value of the REG_NAME
134 * register, setting bits passed in the value.
136 s
->usbphy
[index
- 1] |= value
;
141 case USBPHY_CTRL_CLR
:
142 case USBPHY_DEBUG_CLR
:
143 case USBPHY_DEBUG1_CLR
:
145 * All REG_NAME_CLR register access are in fact targeting the
146 * REG_NAME register. So we change the value of the REG_NAME
147 * register, unsetting bits passed in the value.
149 s
->usbphy
[index
- 2] &= ~value
;
151 case USBPHY_CTRL_TOG
:
152 s
->usbphy
[index
- 3] ^= value
;
153 if ((value
& USBPHY_CTRL_SFTRST
) &&
154 (s
->usbphy
[index
- 3] & USBPHY_CTRL_SFTRST
)) {
155 imx_usbphy_softreset(s
);
161 case USBPHY_DEBUG_TOG
:
162 case USBPHY_DEBUG1_TOG
:
164 * All REG_NAME_TOG register access are in fact targeting the
165 * REG_NAME register. So we change the value of the REG_NAME
166 * register, toggling bits passed in the value.
168 s
->usbphy
[index
- 3] ^= value
;
171 /* Other registers are read-only */
176 static const struct MemoryRegionOps imx_usbphy_ops
= {
177 .read
= imx_usbphy_read
,
178 .write
= imx_usbphy_write
,
179 .endianness
= DEVICE_NATIVE_ENDIAN
,
182 * Our device would not work correctly if the guest was doing
183 * unaligned access. This might not be a limitation on the real
184 * device but in practice there is no reason for a guest to access
185 * this device unaligned.
187 .min_access_size
= 4,
188 .max_access_size
= 4,
193 static void imx_usbphy_realize(DeviceState
*dev
, Error
**errp
)
195 IMXUSBPHYState
*s
= IMX_USBPHY(dev
);
197 memory_region_init_io(&s
->iomem
, OBJECT(s
), &imx_usbphy_ops
, s
,
198 "imx-usbphy", 0x1000);
199 sysbus_init_mmio(SYS_BUS_DEVICE(s
), &s
->iomem
);
202 static void imx_usbphy_class_init(ObjectClass
*klass
, void *data
)
204 DeviceClass
*dc
= DEVICE_CLASS(klass
);
206 dc
->reset
= imx_usbphy_reset
;
207 dc
->vmsd
= &vmstate_imx_usbphy
;
208 dc
->desc
= "i.MX USB PHY Module";
209 dc
->realize
= imx_usbphy_realize
;
212 static const TypeInfo imx_usbphy_info
= {
213 .name
= TYPE_IMX_USBPHY
,
214 .parent
= TYPE_SYS_BUS_DEVICE
,
215 .instance_size
= sizeof(IMXUSBPHYState
),
216 .class_init
= imx_usbphy_class_init
,
219 static void imx_usbphy_register_types(void)
221 type_register_static(&imx_usbphy_info
);
224 type_init(imx_usbphy_register_types
)