|
|
1.1 ! root 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: ! 22: #include "pci_ids.h" ! 23: #include "msi.h" ! 24: #include "pcie.h" ! 25: #include "xio3130_downstream.h" ! 26: ! 27: #define PCI_DEVICE_ID_TI_XIO3130D 0x8233 /* downstream port */ ! 28: #define XIO3130_REVISION 0x1 ! 29: #define XIO3130_MSI_OFFSET 0x70 ! 30: #define XIO3130_MSI_SUPPORTED_FLAGS PCI_MSI_FLAGS_64BIT ! 31: #define XIO3130_MSI_NR_VECTOR 1 ! 32: #define XIO3130_SSVID_OFFSET 0x80 ! 33: #define XIO3130_SSVID_SVID 0 ! 34: #define XIO3130_SSVID_SSID 0 ! 35: #define XIO3130_EXP_OFFSET 0x90 ! 36: #define XIO3130_AER_OFFSET 0x100 ! 37: ! 38: static void xio3130_downstream_write_config(PCIDevice *d, uint32_t address, ! 39: uint32_t val, int len) ! 40: { ! 41: pci_bridge_write_config(d, address, val, len); ! 42: pcie_cap_flr_write_config(d, address, val, len); ! 43: pcie_cap_slot_write_config(d, address, val, len); ! 44: msi_write_config(d, address, val, len); ! 45: pcie_aer_write_config(d, address, val, len); ! 46: } ! 47: ! 48: static void xio3130_downstream_reset(DeviceState *qdev) ! 49: { ! 50: PCIDevice *d = DO_UPCAST(PCIDevice, qdev, qdev); ! 51: msi_reset(d); ! 52: pcie_cap_deverr_reset(d); ! 53: pcie_cap_slot_reset(d); ! 54: pcie_cap_ari_reset(d); ! 55: pci_bridge_reset(qdev); ! 56: } ! 57: ! 58: static int xio3130_downstream_initfn(PCIDevice *d) ! 59: { ! 60: PCIBridge* br = DO_UPCAST(PCIBridge, dev, d); ! 61: PCIEPort *p = DO_UPCAST(PCIEPort, br, br); ! 62: PCIESlot *s = DO_UPCAST(PCIESlot, port, p); ! 63: int rc; ! 64: int tmp; ! 65: ! 66: rc = pci_bridge_initfn(d); ! 67: if (rc < 0) { ! 68: return rc; ! 69: } ! 70: ! 71: pcie_port_init_reg(d); ! 72: pci_config_set_vendor_id(d->config, PCI_VENDOR_ID_TI); ! 73: pci_config_set_device_id(d->config, PCI_DEVICE_ID_TI_XIO3130D); ! 74: d->config[PCI_REVISION_ID] = XIO3130_REVISION; ! 75: ! 76: rc = msi_init(d, XIO3130_MSI_OFFSET, XIO3130_MSI_NR_VECTOR, ! 77: XIO3130_MSI_SUPPORTED_FLAGS & PCI_MSI_FLAGS_64BIT, ! 78: XIO3130_MSI_SUPPORTED_FLAGS & PCI_MSI_FLAGS_MASKBIT); ! 79: if (rc < 0) { ! 80: goto err_bridge; ! 81: } ! 82: rc = pci_bridge_ssvid_init(d, XIO3130_SSVID_OFFSET, ! 83: XIO3130_SSVID_SVID, XIO3130_SSVID_SSID); ! 84: if (rc < 0) { ! 85: goto err_bridge; ! 86: } ! 87: rc = pcie_cap_init(d, XIO3130_EXP_OFFSET, PCI_EXP_TYPE_DOWNSTREAM, ! 88: p->port); ! 89: if (rc < 0) { ! 90: goto err_msi; ! 91: } ! 92: pcie_cap_flr_init(d); ! 93: pcie_cap_deverr_init(d); ! 94: pcie_cap_slot_init(d, s->slot); ! 95: pcie_chassis_create(s->chassis); ! 96: rc = pcie_chassis_add_slot(s); ! 97: if (rc < 0) { ! 98: goto err_pcie_cap; ! 99: } ! 100: pcie_cap_ari_init(d); ! 101: rc = pcie_aer_init(d, XIO3130_AER_OFFSET); ! 102: if (rc < 0) { ! 103: goto err; ! 104: } ! 105: ! 106: return 0; ! 107: ! 108: err: ! 109: pcie_chassis_del_slot(s); ! 110: err_pcie_cap: ! 111: pcie_cap_exit(d); ! 112: err_msi: ! 113: msi_uninit(d); ! 114: err_bridge: ! 115: tmp = pci_bridge_exitfn(d); ! 116: assert(!tmp); ! 117: return rc; ! 118: } ! 119: ! 120: static int xio3130_downstream_exitfn(PCIDevice *d) ! 121: { ! 122: PCIBridge* br = DO_UPCAST(PCIBridge, dev, d); ! 123: PCIEPort *p = DO_UPCAST(PCIEPort, br, br); ! 124: PCIESlot *s = DO_UPCAST(PCIESlot, port, p); ! 125: ! 126: pcie_aer_exit(d); ! 127: pcie_chassis_del_slot(s); ! 128: pcie_cap_exit(d); ! 129: msi_uninit(d); ! 130: return pci_bridge_exitfn(d); ! 131: } ! 132: ! 133: PCIESlot *xio3130_downstream_init(PCIBus *bus, int devfn, bool multifunction, ! 134: const char *bus_name, pci_map_irq_fn map_irq, ! 135: uint8_t port, uint8_t chassis, ! 136: uint16_t slot) ! 137: { ! 138: PCIDevice *d; ! 139: PCIBridge *br; ! 140: DeviceState *qdev; ! 141: ! 142: d = pci_create_multifunction(bus, devfn, multifunction, ! 143: "xio3130-downstream"); ! 144: if (!d) { ! 145: return NULL; ! 146: } ! 147: br = DO_UPCAST(PCIBridge, dev, d); ! 148: ! 149: qdev = &br->dev.qdev; ! 150: pci_bridge_map_irq(br, bus_name, map_irq); ! 151: qdev_prop_set_uint8(qdev, "port", port); ! 152: qdev_prop_set_uint8(qdev, "chassis", chassis); ! 153: qdev_prop_set_uint16(qdev, "slot", slot); ! 154: qdev_init_nofail(qdev); ! 155: ! 156: return DO_UPCAST(PCIESlot, port, DO_UPCAST(PCIEPort, br, br)); ! 157: } ! 158: ! 159: static const VMStateDescription vmstate_xio3130_downstream = { ! 160: .name = "xio3130-express-downstream-port", ! 161: .version_id = 1, ! 162: .minimum_version_id = 1, ! 163: .minimum_version_id_old = 1, ! 164: .post_load = pcie_cap_slot_post_load, ! 165: .fields = (VMStateField[]) { ! 166: VMSTATE_PCIE_DEVICE(port.br.dev, PCIESlot), ! 167: VMSTATE_STRUCT(port.br.dev.exp.aer_log, PCIESlot, 0, ! 168: vmstate_pcie_aer_log, PCIEAERLog), ! 169: VMSTATE_END_OF_LIST() ! 170: } ! 171: }; ! 172: ! 173: static PCIDeviceInfo xio3130_downstream_info = { ! 174: .qdev.name = "xio3130-downstream", ! 175: .qdev.desc = "TI X3130 Downstream Port of PCI Express Switch", ! 176: .qdev.size = sizeof(PCIESlot), ! 177: .qdev.reset = xio3130_downstream_reset, ! 178: .qdev.vmsd = &vmstate_xio3130_downstream, ! 179: ! 180: .is_express = 1, ! 181: .is_bridge = 1, ! 182: .config_write = xio3130_downstream_write_config, ! 183: .init = xio3130_downstream_initfn, ! 184: .exit = xio3130_downstream_exitfn, ! 185: ! 186: .qdev.props = (Property[]) { ! 187: DEFINE_PROP_UINT8("port", PCIESlot, port.port, 0), ! 188: DEFINE_PROP_UINT8("chassis", PCIESlot, chassis, 0), ! 189: DEFINE_PROP_UINT16("slot", PCIESlot, slot, 0), ! 190: DEFINE_PROP_UINT16("aer_log_max", PCIESlot, ! 191: port.br.dev.exp.aer_log.log_max, ! 192: PCIE_AER_LOG_MAX_DEFAULT), ! 193: DEFINE_PROP_END_OF_LIST(), ! 194: } ! 195: }; ! 196: ! 197: static void xio3130_downstream_register(void) ! 198: { ! 199: pci_qdev_register(&xio3130_downstream_info); ! 200: } ! 201: ! 202: device_init(xio3130_downstream_register); ! 203: ! 204: /* ! 205: * Local variables: ! 206: * c-indent-level: 4 ! 207: * c-basic-offset: 4 ! 208: * tab-width: 8 ! 209: * indent-tab-mode: nil ! 210: * End: ! 211: */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.