xref: /openbmc/qemu/hw/usb/imx-usb-phy.c (revision a010bdbe)
1 /*
2  * i.MX USB PHY
3  *
4  * Copyright (c) 2020 Guenter Roeck <linux@roeck-us.net>
5  *
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.
8  *
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.
11  */
12 
13 #include "qemu/osdep.h"
14 #include "hw/usb/imx-usb-phy.h"
15 #include "migration/vmstate.h"
16 #include "qemu/log.h"
17 #include "qemu/module.h"
18 
19 static const VMStateDescription vmstate_imx_usbphy = {
20     .name = TYPE_IMX_USBPHY,
21     .version_id = 1,
22     .minimum_version_id = 1,
23     .fields = (VMStateField[]) {
24         VMSTATE_UINT32_ARRAY(usbphy, IMXUSBPHYState, USBPHY_MAX),
25         VMSTATE_END_OF_LIST()
26     },
27 };
28 
29 static void imx_usbphy_softreset(IMXUSBPHYState *s)
30 {
31     s->usbphy[USBPHY_PWD] = 0x001e1c00;
32     s->usbphy[USBPHY_TX] = 0x10060607;
33     s->usbphy[USBPHY_RX] = 0x00000000;
34     s->usbphy[USBPHY_CTRL] = 0xc0200000;
35 }
36 
37 static void imx_usbphy_reset(DeviceState *dev)
38 {
39     IMXUSBPHYState *s = IMX_USBPHY(dev);
40 
41     s->usbphy[USBPHY_STATUS] = 0x00000000;
42     s->usbphy[USBPHY_DEBUG] = 0x7f180000;
43     s->usbphy[USBPHY_DEBUG0_STATUS] = 0x00000000;
44     s->usbphy[USBPHY_DEBUG1] = 0x00001000;
45     s->usbphy[USBPHY_VERSION] = 0x04020000;
46 
47     imx_usbphy_softreset(s);
48 }
49 
50 static uint64_t imx_usbphy_read(void *opaque, hwaddr offset, unsigned size)
51 {
52     IMXUSBPHYState *s = (IMXUSBPHYState *)opaque;
53     uint32_t index = offset >> 2;
54     uint32_t value;
55 
56     switch (index) {
57     case USBPHY_PWD_SET:
58     case USBPHY_TX_SET:
59     case USBPHY_RX_SET:
60     case USBPHY_CTRL_SET:
61     case USBPHY_DEBUG_SET:
62     case USBPHY_DEBUG1_SET:
63         /*
64          * All REG_NAME_SET register access are in fact targeting the
65          * REG_NAME register.
66          */
67         value = s->usbphy[index - 1];
68         break;
69     case USBPHY_PWD_CLR:
70     case USBPHY_TX_CLR:
71     case USBPHY_RX_CLR:
72     case USBPHY_CTRL_CLR:
73     case USBPHY_DEBUG_CLR:
74     case USBPHY_DEBUG1_CLR:
75         /*
76          * All REG_NAME_CLR register access are in fact targeting the
77          * REG_NAME register.
78          */
79         value = s->usbphy[index - 2];
80         break;
81     case USBPHY_PWD_TOG:
82     case USBPHY_TX_TOG:
83     case USBPHY_RX_TOG:
84     case USBPHY_CTRL_TOG:
85     case USBPHY_DEBUG_TOG:
86     case USBPHY_DEBUG1_TOG:
87         /*
88          * All REG_NAME_TOG register access are in fact targeting the
89          * REG_NAME register.
90          */
91         value = s->usbphy[index - 3];
92         break;
93     default:
94         value = s->usbphy[index];
95         break;
96     }
97     return (uint64_t)value;
98 }
99 
100 static void imx_usbphy_write(void *opaque, hwaddr offset, uint64_t value,
101                              unsigned size)
102 {
103     IMXUSBPHYState *s = (IMXUSBPHYState *)opaque;
104     uint32_t index = offset >> 2;
105 
106     switch (index) {
107     case USBPHY_CTRL:
108         s->usbphy[index] = value;
109         if (value & USBPHY_CTRL_SFTRST) {
110             imx_usbphy_softreset(s);
111         }
112         break;
113     case USBPHY_PWD:
114     case USBPHY_TX:
115     case USBPHY_RX:
116     case USBPHY_STATUS:
117     case USBPHY_DEBUG:
118     case USBPHY_DEBUG1:
119         s->usbphy[index] = value;
120         break;
121     case USBPHY_CTRL_SET:
122         s->usbphy[index - 1] |= value;
123         if (value & USBPHY_CTRL_SFTRST) {
124             imx_usbphy_softreset(s);
125         }
126         break;
127     case USBPHY_PWD_SET:
128     case USBPHY_TX_SET:
129     case USBPHY_RX_SET:
130     case USBPHY_DEBUG_SET:
131     case USBPHY_DEBUG1_SET:
132         /*
133          * All REG_NAME_SET register access are in fact targeting the
134          * REG_NAME register. So we change the value of the REG_NAME
135          * register, setting bits passed in the value.
136          */
137         s->usbphy[index - 1] |= value;
138         break;
139     case USBPHY_PWD_CLR:
140     case USBPHY_TX_CLR:
141     case USBPHY_RX_CLR:
142     case USBPHY_CTRL_CLR:
143     case USBPHY_DEBUG_CLR:
144     case USBPHY_DEBUG1_CLR:
145         /*
146          * All REG_NAME_CLR register access are in fact targeting the
147          * REG_NAME register. So we change the value of the REG_NAME
148          * register, unsetting bits passed in the value.
149          */
150         s->usbphy[index - 2] &= ~value;
151         break;
152     case USBPHY_CTRL_TOG:
153         s->usbphy[index - 3] ^= value;
154         if ((value & USBPHY_CTRL_SFTRST) &&
155             (s->usbphy[index - 3] & USBPHY_CTRL_SFTRST)) {
156             imx_usbphy_softreset(s);
157         }
158         break;
159     case USBPHY_PWD_TOG:
160     case USBPHY_TX_TOG:
161     case USBPHY_RX_TOG:
162     case USBPHY_DEBUG_TOG:
163     case USBPHY_DEBUG1_TOG:
164         /*
165          * All REG_NAME_TOG register access are in fact targeting the
166          * REG_NAME register. So we change the value of the REG_NAME
167          * register, toggling bits passed in the value.
168          */
169         s->usbphy[index - 3] ^= value;
170         break;
171     default:
172         /* Other registers are read-only */
173         break;
174     }
175 }
176 
177 static const struct MemoryRegionOps imx_usbphy_ops = {
178     .read = imx_usbphy_read,
179     .write = imx_usbphy_write,
180     .endianness = DEVICE_NATIVE_ENDIAN,
181     .valid = {
182         /*
183          * Our device would not work correctly if the guest was doing
184          * unaligned access. This might not be a limitation on the real
185          * device but in practice there is no reason for a guest to access
186          * this device unaligned.
187          */
188         .min_access_size = 4,
189         .max_access_size = 4,
190         .unaligned = false,
191     },
192 };
193 
194 static void imx_usbphy_realize(DeviceState *dev, Error **errp)
195 {
196     IMXUSBPHYState *s = IMX_USBPHY(dev);
197 
198     memory_region_init_io(&s->iomem, OBJECT(s), &imx_usbphy_ops, s,
199                           "imx-usbphy", 0x1000);
200     sysbus_init_mmio(SYS_BUS_DEVICE(s), &s->iomem);
201 }
202 
203 static void imx_usbphy_class_init(ObjectClass *klass, void *data)
204 {
205     DeviceClass *dc = DEVICE_CLASS(klass);
206 
207     dc->reset = imx_usbphy_reset;
208     dc->vmsd = &vmstate_imx_usbphy;
209     dc->desc = "i.MX USB PHY Module";
210     dc->realize = imx_usbphy_realize;
211 }
212 
213 static const TypeInfo imx_usbphy_info = {
214     .name          = TYPE_IMX_USBPHY,
215     .parent        = TYPE_SYS_BUS_DEVICE,
216     .instance_size = sizeof(IMXUSBPHYState),
217     .class_init    = imx_usbphy_class_init,
218 };
219 
220 static void imx_usbphy_register_types(void)
221 {
222     type_register_static(&imx_usbphy_info);
223 }
224 
225 type_init(imx_usbphy_register_types)
226