1
2
3
4
5
6
7
8
9
10
11
12
13#include "qemu/osdep.h"
14#include "hw/usb/imx-usb-phy.h"
15#include "migration/vmstate.h"
16#include "qemu/module.h"
17
18static const VMStateDescription vmstate_imx_usbphy = {
19 .name = TYPE_IMX_USBPHY,
20 .version_id = 1,
21 .minimum_version_id = 1,
22 .fields = (VMStateField[]) {
23 VMSTATE_UINT32_ARRAY(usbphy, IMXUSBPHYState, USBPHY_MAX),
24 VMSTATE_END_OF_LIST()
25 },
26};
27
28static void imx_usbphy_softreset(IMXUSBPHYState *s)
29{
30 s->usbphy[USBPHY_PWD] = 0x001e1c00;
31 s->usbphy[USBPHY_TX] = 0x10060607;
32 s->usbphy[USBPHY_RX] = 0x00000000;
33 s->usbphy[USBPHY_CTRL] = 0xc0200000;
34}
35
36static void imx_usbphy_reset(DeviceState *dev)
37{
38 IMXUSBPHYState *s = IMX_USBPHY(dev);
39
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;
45
46 imx_usbphy_softreset(s);
47}
48
49static uint64_t imx_usbphy_read(void *opaque, hwaddr offset, unsigned size)
50{
51 IMXUSBPHYState *s = (IMXUSBPHYState *)opaque;
52 uint32_t index = offset >> 2;
53 uint32_t value;
54
55 switch (index) {
56 case USBPHY_PWD_SET:
57 case USBPHY_TX_SET:
58 case USBPHY_RX_SET:
59 case USBPHY_CTRL_SET:
60 case USBPHY_DEBUG_SET:
61 case USBPHY_DEBUG1_SET:
62
63
64
65
66 value = s->usbphy[index - 1];
67 break;
68 case USBPHY_PWD_CLR:
69 case USBPHY_TX_CLR:
70 case USBPHY_RX_CLR:
71 case USBPHY_CTRL_CLR:
72 case USBPHY_DEBUG_CLR:
73 case USBPHY_DEBUG1_CLR:
74
75
76
77
78 value = s->usbphy[index - 2];
79 break;
80 case USBPHY_PWD_TOG:
81 case USBPHY_TX_TOG:
82 case USBPHY_RX_TOG:
83 case USBPHY_CTRL_TOG:
84 case USBPHY_DEBUG_TOG:
85 case USBPHY_DEBUG1_TOG:
86
87
88
89
90 value = s->usbphy[index - 3];
91 break;
92 default:
93 value = s->usbphy[index];
94 break;
95 }
96 return (uint64_t)value;
97}
98
99static void imx_usbphy_write(void *opaque, hwaddr offset, uint64_t value,
100 unsigned size)
101{
102 IMXUSBPHYState *s = (IMXUSBPHYState *)opaque;
103 uint32_t index = offset >> 2;
104
105 switch (index) {
106 case USBPHY_CTRL:
107 s->usbphy[index] = value;
108 if (value & USBPHY_CTRL_SFTRST) {
109 imx_usbphy_softreset(s);
110 }
111 break;
112 case USBPHY_PWD:
113 case USBPHY_TX:
114 case USBPHY_RX:
115 case USBPHY_STATUS:
116 case USBPHY_DEBUG:
117 case USBPHY_DEBUG1:
118 s->usbphy[index] = value;
119 break;
120 case USBPHY_CTRL_SET:
121 s->usbphy[index - 1] |= value;
122 if (value & USBPHY_CTRL_SFTRST) {
123 imx_usbphy_softreset(s);
124 }
125 break;
126 case USBPHY_PWD_SET:
127 case USBPHY_TX_SET:
128 case USBPHY_RX_SET:
129 case USBPHY_DEBUG_SET:
130 case USBPHY_DEBUG1_SET:
131
132
133
134
135
136 s->usbphy[index - 1] |= value;
137 break;
138 case USBPHY_PWD_CLR:
139 case USBPHY_TX_CLR:
140 case USBPHY_RX_CLR:
141 case USBPHY_CTRL_CLR:
142 case USBPHY_DEBUG_CLR:
143 case USBPHY_DEBUG1_CLR:
144
145
146
147
148
149 s->usbphy[index - 2] &= ~value;
150 break;
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);
156 }
157 break;
158 case USBPHY_PWD_TOG:
159 case USBPHY_TX_TOG:
160 case USBPHY_RX_TOG:
161 case USBPHY_DEBUG_TOG:
162 case USBPHY_DEBUG1_TOG:
163
164
165
166
167
168 s->usbphy[index - 3] ^= value;
169 break;
170 default:
171
172 break;
173 }
174}
175
176static const struct MemoryRegionOps imx_usbphy_ops = {
177 .read = imx_usbphy_read,
178 .write = imx_usbphy_write,
179 .endianness = DEVICE_NATIVE_ENDIAN,
180 .valid = {
181
182
183
184
185
186
187 .min_access_size = 4,
188 .max_access_size = 4,
189 .unaligned = false,
190 },
191};
192
193static void imx_usbphy_realize(DeviceState *dev, Error **errp)
194{
195 IMXUSBPHYState *s = IMX_USBPHY(dev);
196
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);
200}
201
202static void imx_usbphy_class_init(ObjectClass *klass, void *data)
203{
204 DeviceClass *dc = DEVICE_CLASS(klass);
205
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;
210}
211
212static 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,
217};
218
219static void imx_usbphy_register_types(void)
220{
221 type_register_static(&imx_usbphy_info);
222}
223
224type_init(imx_usbphy_register_types)
225