imx_gpcv2.c 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. /*
  2. * Copyright (c) 2018, Impinj, Inc.
  3. *
  4. * i.MX7 GPCv2 block emulation code
  5. *
  6. * Author: Andrey Smirnov <andrew.smirnov@gmail.com>
  7. *
  8. * This work is licensed under the terms of the GNU GPL, version 2 or later.
  9. * See the COPYING file in the top-level directory.
  10. */
  11. #include "qemu/osdep.h"
  12. #include "hw/intc/imx_gpcv2.h"
  13. #include "migration/vmstate.h"
  14. #include "qemu/log.h"
  15. #include "qemu/module.h"
  16. #define GPC_PU_PGC_SW_PUP_REQ 0x0f8
  17. #define GPC_PU_PGC_SW_PDN_REQ 0x104
  18. #define USB_HSIC_PHY_SW_Pxx_REQ BIT(4)
  19. #define USB_OTG2_PHY_SW_Pxx_REQ BIT(3)
  20. #define USB_OTG1_PHY_SW_Pxx_REQ BIT(2)
  21. #define PCIE_PHY_SW_Pxx_REQ BIT(1)
  22. #define MIPI_PHY_SW_Pxx_REQ BIT(0)
  23. static void imx_gpcv2_reset(DeviceState *dev)
  24. {
  25. IMXGPCv2State *s = IMX_GPCV2(dev);
  26. memset(s->regs, 0, sizeof(s->regs));
  27. }
  28. static uint64_t imx_gpcv2_read(void *opaque, hwaddr offset,
  29. unsigned size)
  30. {
  31. IMXGPCv2State *s = opaque;
  32. return s->regs[offset / sizeof(uint32_t)];
  33. }
  34. static void imx_gpcv2_write(void *opaque, hwaddr offset,
  35. uint64_t value, unsigned size)
  36. {
  37. IMXGPCv2State *s = opaque;
  38. const size_t idx = offset / sizeof(uint32_t);
  39. s->regs[idx] = value;
  40. /*
  41. * Real HW will clear those bits once as a way to indicate that
  42. * power up request is complete
  43. */
  44. if (offset == GPC_PU_PGC_SW_PUP_REQ ||
  45. offset == GPC_PU_PGC_SW_PDN_REQ) {
  46. s->regs[idx] &= ~(USB_HSIC_PHY_SW_Pxx_REQ |
  47. USB_OTG2_PHY_SW_Pxx_REQ |
  48. USB_OTG1_PHY_SW_Pxx_REQ |
  49. PCIE_PHY_SW_Pxx_REQ |
  50. MIPI_PHY_SW_Pxx_REQ);
  51. }
  52. }
  53. static const struct MemoryRegionOps imx_gpcv2_ops = {
  54. .read = imx_gpcv2_read,
  55. .write = imx_gpcv2_write,
  56. .endianness = DEVICE_NATIVE_ENDIAN,
  57. .impl = {
  58. /*
  59. * Our device would not work correctly if the guest was doing
  60. * unaligned access. This might not be a limitation on the real
  61. * device but in practice there is no reason for a guest to access
  62. * this device unaligned.
  63. */
  64. .min_access_size = 4,
  65. .max_access_size = 4,
  66. .unaligned = false,
  67. },
  68. };
  69. static void imx_gpcv2_init(Object *obj)
  70. {
  71. SysBusDevice *sd = SYS_BUS_DEVICE(obj);
  72. IMXGPCv2State *s = IMX_GPCV2(obj);
  73. memory_region_init_io(&s->iomem,
  74. obj,
  75. &imx_gpcv2_ops,
  76. s,
  77. TYPE_IMX_GPCV2 ".iomem",
  78. sizeof(s->regs));
  79. sysbus_init_mmio(sd, &s->iomem);
  80. }
  81. static const VMStateDescription vmstate_imx_gpcv2 = {
  82. .name = TYPE_IMX_GPCV2,
  83. .version_id = 1,
  84. .minimum_version_id = 1,
  85. .fields = (VMStateField[]) {
  86. VMSTATE_UINT32_ARRAY(regs, IMXGPCv2State, GPC_NUM),
  87. VMSTATE_END_OF_LIST()
  88. },
  89. };
  90. static void imx_gpcv2_class_init(ObjectClass *klass, void *data)
  91. {
  92. DeviceClass *dc = DEVICE_CLASS(klass);
  93. dc->reset = imx_gpcv2_reset;
  94. dc->vmsd = &vmstate_imx_gpcv2;
  95. dc->desc = "i.MX GPCv2 Module";
  96. }
  97. static const TypeInfo imx_gpcv2_info = {
  98. .name = TYPE_IMX_GPCV2,
  99. .parent = TYPE_SYS_BUS_DEVICE,
  100. .instance_size = sizeof(IMXGPCv2State),
  101. .instance_init = imx_gpcv2_init,
  102. .class_init = imx_gpcv2_class_init,
  103. };
  104. static void imx_gpcv2_register_type(void)
  105. {
  106. type_register_static(&imx_gpcv2_info);
  107. }
  108. type_init(imx_gpcv2_register_type)