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