xio3130_downstream.c 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189
  1. /*
  2. * x3130_downstream.c
  3. * TI X3130 pci express downstream port switch
  4. *
  5. * Copyright (c) 2010 Isaku Yamahata <yamahata at valinux co jp>
  6. * VA Linux Systems Japan K.K.
  7. *
  8. * This program is free software; you can redistribute it and/or modify
  9. * it under the terms of the GNU General Public License as published by
  10. * the Free Software Foundation; either version 2 of the License, or
  11. * (at your option) any later version.
  12. *
  13. * This program is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. * GNU General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU General Public License along
  19. * with this program; if not, see <http://www.gnu.org/licenses/>.
  20. */
  21. #include "qemu/osdep.h"
  22. #include "hw/pci/pci_ids.h"
  23. #include "hw/pci/msi.h"
  24. #include "hw/pci/pcie.h"
  25. #include "hw/pci/pcie_port.h"
  26. #include "hw/qdev-properties.h"
  27. #include "migration/vmstate.h"
  28. #include "qapi/error.h"
  29. #include "qemu/module.h"
  30. #include "hw/pci-bridge/xio3130_downstream.h"
  31. #define PCI_DEVICE_ID_TI_XIO3130D 0x8233 /* downstream port */
  32. #define XIO3130_REVISION 0x1
  33. #define XIO3130_MSI_OFFSET 0x70
  34. #define XIO3130_MSI_SUPPORTED_FLAGS PCI_MSI_FLAGS_64BIT
  35. #define XIO3130_MSI_NR_VECTOR 1
  36. #define XIO3130_SSVID_OFFSET 0x80
  37. #define XIO3130_SSVID_SVID 0
  38. #define XIO3130_SSVID_SSID 0
  39. #define XIO3130_EXP_OFFSET 0x90
  40. #define XIO3130_AER_OFFSET 0x100
  41. static void xio3130_downstream_write_config(PCIDevice *d, uint32_t address,
  42. uint32_t val, int len)
  43. {
  44. uint16_t slt_ctl, slt_sta;
  45. pcie_cap_slot_get(d, &slt_ctl, &slt_sta);
  46. pci_bridge_write_config(d, address, val, len);
  47. pcie_cap_flr_write_config(d, address, val, len);
  48. pcie_cap_slot_write_config(d, slt_ctl, slt_sta, address, val, len);
  49. pcie_aer_write_config(d, address, val, len);
  50. }
  51. static void xio3130_downstream_reset(DeviceState *qdev)
  52. {
  53. PCIDevice *d = PCI_DEVICE(qdev);
  54. pcie_cap_deverr_reset(d);
  55. pcie_cap_slot_reset(d);
  56. pcie_cap_arifwd_reset(d);
  57. pci_bridge_reset(qdev);
  58. }
  59. static void xio3130_downstream_realize(PCIDevice *d, Error **errp)
  60. {
  61. PCIEPort *p = PCIE_PORT(d);
  62. PCIESlot *s = PCIE_SLOT(d);
  63. int rc;
  64. pci_bridge_initfn(d, TYPE_PCIE_BUS);
  65. pcie_port_init_reg(d);
  66. rc = msi_init(d, XIO3130_MSI_OFFSET, XIO3130_MSI_NR_VECTOR,
  67. XIO3130_MSI_SUPPORTED_FLAGS & PCI_MSI_FLAGS_64BIT,
  68. XIO3130_MSI_SUPPORTED_FLAGS & PCI_MSI_FLAGS_MASKBIT,
  69. errp);
  70. if (rc < 0) {
  71. assert(rc == -ENOTSUP);
  72. goto err_bridge;
  73. }
  74. rc = pci_bridge_ssvid_init(d, XIO3130_SSVID_OFFSET,
  75. XIO3130_SSVID_SVID, XIO3130_SSVID_SSID,
  76. errp);
  77. if (rc < 0) {
  78. goto err_msi;
  79. }
  80. rc = pcie_cap_init(d, XIO3130_EXP_OFFSET, PCI_EXP_TYPE_DOWNSTREAM,
  81. p->port, errp);
  82. if (rc < 0) {
  83. goto err_msi;
  84. }
  85. pcie_cap_flr_init(d);
  86. pcie_cap_deverr_init(d);
  87. pcie_cap_slot_init(d, s);
  88. pcie_cap_arifwd_init(d);
  89. pcie_chassis_create(s->chassis);
  90. rc = pcie_chassis_add_slot(s);
  91. if (rc < 0) {
  92. error_setg(errp, "Can't add chassis slot, error %d", rc);
  93. goto err_pcie_cap;
  94. }
  95. rc = pcie_aer_init(d, PCI_ERR_VER, XIO3130_AER_OFFSET,
  96. PCI_ERR_SIZEOF, errp);
  97. if (rc < 0) {
  98. goto err;
  99. }
  100. return;
  101. err:
  102. pcie_chassis_del_slot(s);
  103. err_pcie_cap:
  104. pcie_cap_exit(d);
  105. err_msi:
  106. msi_uninit(d);
  107. err_bridge:
  108. pci_bridge_exitfn(d);
  109. }
  110. static void xio3130_downstream_exitfn(PCIDevice *d)
  111. {
  112. PCIESlot *s = PCIE_SLOT(d);
  113. pcie_aer_exit(d);
  114. pcie_chassis_del_slot(s);
  115. pcie_cap_exit(d);
  116. msi_uninit(d);
  117. pci_bridge_exitfn(d);
  118. }
  119. static const Property xio3130_downstream_props[] = {
  120. DEFINE_PROP_BIT(COMPAT_PROP_PCP, PCIDevice, cap_present,
  121. QEMU_PCIE_SLTCAP_PCP_BITNR, true),
  122. };
  123. static const VMStateDescription vmstate_xio3130_downstream = {
  124. .name = "xio3130-express-downstream-port",
  125. .priority = MIG_PRI_PCI_BUS,
  126. .version_id = 1,
  127. .minimum_version_id = 1,
  128. .post_load = pcie_cap_slot_post_load,
  129. .fields = (const VMStateField[]) {
  130. VMSTATE_PCI_DEVICE(parent_obj.parent_obj.parent_obj, PCIESlot),
  131. VMSTATE_STRUCT(parent_obj.parent_obj.parent_obj.exp.aer_log,
  132. PCIESlot, 0, vmstate_pcie_aer_log, PCIEAERLog),
  133. VMSTATE_END_OF_LIST()
  134. }
  135. };
  136. static void xio3130_downstream_class_init(ObjectClass *klass, void *data)
  137. {
  138. DeviceClass *dc = DEVICE_CLASS(klass);
  139. PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
  140. k->config_write = xio3130_downstream_write_config;
  141. k->realize = xio3130_downstream_realize;
  142. k->exit = xio3130_downstream_exitfn;
  143. k->vendor_id = PCI_VENDOR_ID_TI;
  144. k->device_id = PCI_DEVICE_ID_TI_XIO3130D;
  145. k->revision = XIO3130_REVISION;
  146. set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories);
  147. dc->desc = "TI X3130 Downstream Port of PCI Express Switch";
  148. device_class_set_legacy_reset(dc, xio3130_downstream_reset);
  149. dc->vmsd = &vmstate_xio3130_downstream;
  150. device_class_set_props(dc, xio3130_downstream_props);
  151. }
  152. static const TypeInfo xio3130_downstream_info = {
  153. .name = TYPE_XIO3130_DOWNSTREAM,
  154. .parent = TYPE_PCIE_SLOT,
  155. .class_init = xio3130_downstream_class_init,
  156. .interfaces = (InterfaceInfo[]) {
  157. { INTERFACE_PCIE_DEVICE },
  158. { }
  159. },
  160. };
  161. static void xio3130_downstream_register_types(void)
  162. {
  163. type_register_static(&xio3130_downstream_info);
  164. }
  165. type_init(xio3130_downstream_register_types)