xlnx-versal-usb2-ctrl-regs.c 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228
  1. /*
  2. * QEMU model of the VersalUsb2CtrlRegs Register control/Status block for
  3. * USB2.0 controller
  4. *
  5. * This module should control phy_reset, permanent device plugs, frame length
  6. * time adjust & setting of coherency paths. None of which are emulated in
  7. * present model.
  8. *
  9. * Copyright (c) 2020 Xilinx Inc. Vikram Garhwal <fnu.vikram@xilinx.com>
  10. *
  11. * Permission is hereby granted, free of charge, to any person obtaining a copy
  12. * of this software and associated documentation files (the "Software"), to deal
  13. * in the Software without restriction, including without limitation the rights
  14. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  15. * copies of the Software, and to permit persons to whom the Software is
  16. * furnished to do so, subject to the following conditions:
  17. *
  18. * The above copyright notice and this permission notice shall be included in
  19. * all copies or substantial portions of the Software.
  20. *
  21. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  22. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  23. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  24. * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  25. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  26. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  27. * THE SOFTWARE.
  28. */
  29. #include "qemu/osdep.h"
  30. #include "hw/sysbus.h"
  31. #include "hw/irq.h"
  32. #include "hw/register.h"
  33. #include "qemu/bitops.h"
  34. #include "qom/object.h"
  35. #include "migration/vmstate.h"
  36. #include "hw/usb/xlnx-versal-usb2-ctrl-regs.h"
  37. #ifndef XILINX_VERSAL_USB2_CTRL_REGS_ERR_DEBUG
  38. #define XILINX_VERSAL_USB2_CTRL_REGS_ERR_DEBUG 0
  39. #endif
  40. REG32(BUS_FILTER, 0x30)
  41. FIELD(BUS_FILTER, BYPASS, 0, 4)
  42. REG32(PORT, 0x34)
  43. FIELD(PORT, HOST_SMI_BAR_WR, 4, 1)
  44. FIELD(PORT, HOST_SMI_PCI_CMD_REG_WR, 3, 1)
  45. FIELD(PORT, HOST_MSI_ENABLE, 2, 1)
  46. FIELD(PORT, PWR_CTRL_PRSNT, 1, 1)
  47. FIELD(PORT, HUB_PERM_ATTACH, 0, 1)
  48. REG32(JITTER_ADJUST, 0x38)
  49. FIELD(JITTER_ADJUST, FLADJ, 0, 6)
  50. REG32(BIGENDIAN, 0x40)
  51. FIELD(BIGENDIAN, ENDIAN_GS, 0, 1)
  52. REG32(COHERENCY, 0x44)
  53. FIELD(COHERENCY, USB_COHERENCY, 0, 1)
  54. REG32(XHC_BME, 0x48)
  55. FIELD(XHC_BME, XHC_BME, 0, 1)
  56. REG32(REG_CTRL, 0x60)
  57. FIELD(REG_CTRL, SLVERR_ENABLE, 0, 1)
  58. REG32(IR_STATUS, 0x64)
  59. FIELD(IR_STATUS, HOST_SYS_ERR, 1, 1)
  60. FIELD(IR_STATUS, ADDR_DEC_ERR, 0, 1)
  61. REG32(IR_MASK, 0x68)
  62. FIELD(IR_MASK, HOST_SYS_ERR, 1, 1)
  63. FIELD(IR_MASK, ADDR_DEC_ERR, 0, 1)
  64. REG32(IR_ENABLE, 0x6c)
  65. FIELD(IR_ENABLE, HOST_SYS_ERR, 1, 1)
  66. FIELD(IR_ENABLE, ADDR_DEC_ERR, 0, 1)
  67. REG32(IR_DISABLE, 0x70)
  68. FIELD(IR_DISABLE, HOST_SYS_ERR, 1, 1)
  69. FIELD(IR_DISABLE, ADDR_DEC_ERR, 0, 1)
  70. REG32(USB3, 0x78)
  71. static void ir_update_irq(VersalUsb2CtrlRegs *s)
  72. {
  73. bool pending = s->regs[R_IR_STATUS] & ~s->regs[R_IR_MASK];
  74. qemu_set_irq(s->irq_ir, pending);
  75. }
  76. static void ir_status_postw(RegisterInfo *reg, uint64_t val64)
  77. {
  78. VersalUsb2CtrlRegs *s = XILINX_VERSAL_USB2_CTRL_REGS(reg->opaque);
  79. /*
  80. * TODO: This should also clear USBSTS.HSE field in USB XHCI register.
  81. * May be combine both the modules.
  82. */
  83. ir_update_irq(s);
  84. }
  85. static uint64_t ir_enable_prew(RegisterInfo *reg, uint64_t val64)
  86. {
  87. VersalUsb2CtrlRegs *s = XILINX_VERSAL_USB2_CTRL_REGS(reg->opaque);
  88. uint32_t val = val64;
  89. s->regs[R_IR_MASK] &= ~val;
  90. ir_update_irq(s);
  91. return 0;
  92. }
  93. static uint64_t ir_disable_prew(RegisterInfo *reg, uint64_t val64)
  94. {
  95. VersalUsb2CtrlRegs *s = XILINX_VERSAL_USB2_CTRL_REGS(reg->opaque);
  96. uint32_t val = val64;
  97. s->regs[R_IR_MASK] |= val;
  98. ir_update_irq(s);
  99. return 0;
  100. }
  101. static const RegisterAccessInfo usb2_ctrl_regs_regs_info[] = {
  102. { .name = "BUS_FILTER", .addr = A_BUS_FILTER,
  103. .rsvd = 0xfffffff0,
  104. },{ .name = "PORT", .addr = A_PORT,
  105. .rsvd = 0xffffffe0,
  106. },{ .name = "JITTER_ADJUST", .addr = A_JITTER_ADJUST,
  107. .reset = 0x20,
  108. .rsvd = 0xffffffc0,
  109. },{ .name = "BIGENDIAN", .addr = A_BIGENDIAN,
  110. .rsvd = 0xfffffffe,
  111. },{ .name = "COHERENCY", .addr = A_COHERENCY,
  112. .rsvd = 0xfffffffe,
  113. },{ .name = "XHC_BME", .addr = A_XHC_BME,
  114. .reset = 0x1,
  115. .rsvd = 0xfffffffe,
  116. },{ .name = "REG_CTRL", .addr = A_REG_CTRL,
  117. .rsvd = 0xfffffffe,
  118. },{ .name = "IR_STATUS", .addr = A_IR_STATUS,
  119. .rsvd = 0xfffffffc,
  120. .w1c = 0x3,
  121. .post_write = ir_status_postw,
  122. },{ .name = "IR_MASK", .addr = A_IR_MASK,
  123. .reset = 0x3,
  124. .rsvd = 0xfffffffc,
  125. .ro = 0x3,
  126. },{ .name = "IR_ENABLE", .addr = A_IR_ENABLE,
  127. .rsvd = 0xfffffffc,
  128. .pre_write = ir_enable_prew,
  129. },{ .name = "IR_DISABLE", .addr = A_IR_DISABLE,
  130. .rsvd = 0xfffffffc,
  131. .pre_write = ir_disable_prew,
  132. },{ .name = "USB3", .addr = A_USB3,
  133. }
  134. };
  135. static void usb2_ctrl_regs_reset_init(Object *obj, ResetType type)
  136. {
  137. VersalUsb2CtrlRegs *s = XILINX_VERSAL_USB2_CTRL_REGS(obj);
  138. unsigned int i;
  139. for (i = 0; i < ARRAY_SIZE(s->regs_info); ++i) {
  140. register_reset(&s->regs_info[i]);
  141. }
  142. }
  143. static void usb2_ctrl_regs_reset_hold(Object *obj, ResetType type)
  144. {
  145. VersalUsb2CtrlRegs *s = XILINX_VERSAL_USB2_CTRL_REGS(obj);
  146. ir_update_irq(s);
  147. }
  148. static const MemoryRegionOps usb2_ctrl_regs_ops = {
  149. .read = register_read_memory,
  150. .write = register_write_memory,
  151. .endianness = DEVICE_LITTLE_ENDIAN,
  152. .valid = {
  153. .min_access_size = 4,
  154. .max_access_size = 4,
  155. },
  156. };
  157. static void usb2_ctrl_regs_init(Object *obj)
  158. {
  159. VersalUsb2CtrlRegs *s = XILINX_VERSAL_USB2_CTRL_REGS(obj);
  160. SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
  161. RegisterInfoArray *reg_array;
  162. memory_region_init(&s->iomem, obj, TYPE_XILINX_VERSAL_USB2_CTRL_REGS,
  163. USB2_REGS_R_MAX * 4);
  164. reg_array =
  165. register_init_block32(DEVICE(obj), usb2_ctrl_regs_regs_info,
  166. ARRAY_SIZE(usb2_ctrl_regs_regs_info),
  167. s->regs_info, s->regs,
  168. &usb2_ctrl_regs_ops,
  169. XILINX_VERSAL_USB2_CTRL_REGS_ERR_DEBUG,
  170. USB2_REGS_R_MAX * 4);
  171. memory_region_add_subregion(&s->iomem,
  172. 0x0,
  173. &reg_array->mem);
  174. sysbus_init_mmio(sbd, &s->iomem);
  175. sysbus_init_irq(sbd, &s->irq_ir);
  176. }
  177. static const VMStateDescription vmstate_usb2_ctrl_regs = {
  178. .name = TYPE_XILINX_VERSAL_USB2_CTRL_REGS,
  179. .version_id = 1,
  180. .minimum_version_id = 1,
  181. .fields = (const VMStateField[]) {
  182. VMSTATE_UINT32_ARRAY(regs, VersalUsb2CtrlRegs, USB2_REGS_R_MAX),
  183. VMSTATE_END_OF_LIST(),
  184. }
  185. };
  186. static void usb2_ctrl_regs_class_init(ObjectClass *klass, void *data)
  187. {
  188. DeviceClass *dc = DEVICE_CLASS(klass);
  189. ResettableClass *rc = RESETTABLE_CLASS(klass);
  190. rc->phases.enter = usb2_ctrl_regs_reset_init;
  191. rc->phases.hold = usb2_ctrl_regs_reset_hold;
  192. dc->vmsd = &vmstate_usb2_ctrl_regs;
  193. }
  194. static const TypeInfo usb2_ctrl_regs_info = {
  195. .name = TYPE_XILINX_VERSAL_USB2_CTRL_REGS,
  196. .parent = TYPE_SYS_BUS_DEVICE,
  197. .instance_size = sizeof(VersalUsb2CtrlRegs),
  198. .class_init = usb2_ctrl_regs_class_init,
  199. .instance_init = usb2_ctrl_regs_init,
  200. };
  201. static void usb2_ctrl_regs_register_types(void)
  202. {
  203. type_register_static(&usb2_ctrl_regs_info);
  204. }
  205. type_init(usb2_ctrl_regs_register_types)