|
|
1.1 ! root 1: /* ! 2: * xio3130_upstream.c ! 3: * TI X3130 pci express upstream 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_upstream.h" ! 26: ! 27: #define PCI_DEVICE_ID_TI_XIO3130U 0x8232 /* upstream port */ ! 28: #define XIO3130_REVISION 0x2 ! 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_upstream_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: msi_write_config(d, address, val, len); ! 44: pcie_aer_write_config(d, address, val, len); ! 45: } ! 46: ! 47: static void xio3130_upstream_reset(DeviceState *qdev) ! 48: { ! 49: PCIDevice *d = DO_UPCAST(PCIDevice, qdev, qdev); ! 50: msi_reset(d); ! 51: pci_bridge_reset(qdev); ! 52: pcie_cap_deverr_reset(d); ! 53: } ! 54: ! 55: static int xio3130_upstream_initfn(PCIDevice *d) ! 56: { ! 57: PCIBridge* br = DO_UPCAST(PCIBridge, dev, d); ! 58: PCIEPort *p = DO_UPCAST(PCIEPort, br, br); ! 59: int rc; ! 60: int tmp; ! 61: ! 62: rc = pci_bridge_initfn(d); ! 63: if (rc < 0) { ! 64: return rc; ! 65: } ! 66: ! 67: pcie_port_init_reg(d); ! 68: pci_config_set_vendor_id(d->config, PCI_VENDOR_ID_TI); ! 69: pci_config_set_device_id(d->config, PCI_DEVICE_ID_TI_XIO3130U); ! 70: d->config[PCI_REVISION_ID] = XIO3130_REVISION; ! 71: ! 72: rc = msi_init(d, XIO3130_MSI_OFFSET, XIO3130_MSI_NR_VECTOR, ! 73: XIO3130_MSI_SUPPORTED_FLAGS & PCI_MSI_FLAGS_64BIT, ! 74: XIO3130_MSI_SUPPORTED_FLAGS & PCI_MSI_FLAGS_MASKBIT); ! 75: if (rc < 0) { ! 76: goto err_bridge; ! 77: } ! 78: rc = pci_bridge_ssvid_init(d, XIO3130_SSVID_OFFSET, ! 79: XIO3130_SSVID_SVID, XIO3130_SSVID_SSID); ! 80: if (rc < 0) { ! 81: goto err_bridge; ! 82: } ! 83: rc = pcie_cap_init(d, XIO3130_EXP_OFFSET, PCI_EXP_TYPE_UPSTREAM, ! 84: p->port); ! 85: if (rc < 0) { ! 86: goto err_msi; ! 87: } ! 88: pcie_cap_flr_init(d); ! 89: pcie_cap_deverr_init(d); ! 90: rc = pcie_aer_init(d, XIO3130_AER_OFFSET); ! 91: if (rc < 0) { ! 92: goto err; ! 93: } ! 94: ! 95: return 0; ! 96: ! 97: err: ! 98: pcie_cap_exit(d); ! 99: err_msi: ! 100: msi_uninit(d); ! 101: err_bridge: ! 102: tmp = pci_bridge_exitfn(d); ! 103: assert(!tmp); ! 104: return rc; ! 105: } ! 106: ! 107: static int xio3130_upstream_exitfn(PCIDevice *d) ! 108: { ! 109: pcie_aer_exit(d); ! 110: pcie_cap_exit(d); ! 111: msi_uninit(d); ! 112: return pci_bridge_exitfn(d); ! 113: } ! 114: ! 115: PCIEPort *xio3130_upstream_init(PCIBus *bus, int devfn, bool multifunction, ! 116: const char *bus_name, pci_map_irq_fn map_irq, ! 117: uint8_t port) ! 118: { ! 119: PCIDevice *d; ! 120: PCIBridge *br; ! 121: DeviceState *qdev; ! 122: ! 123: d = pci_create_multifunction(bus, devfn, multifunction, "x3130-upstream"); ! 124: if (!d) { ! 125: return NULL; ! 126: } ! 127: br = DO_UPCAST(PCIBridge, dev, d); ! 128: ! 129: qdev = &br->dev.qdev; ! 130: pci_bridge_map_irq(br, bus_name, map_irq); ! 131: qdev_prop_set_uint8(qdev, "port", port); ! 132: qdev_init_nofail(qdev); ! 133: ! 134: return DO_UPCAST(PCIEPort, br, br); ! 135: } ! 136: ! 137: static const VMStateDescription vmstate_xio3130_upstream = { ! 138: .name = "xio3130-express-upstream-port", ! 139: .version_id = 1, ! 140: .minimum_version_id = 1, ! 141: .minimum_version_id_old = 1, ! 142: .fields = (VMStateField[]) { ! 143: VMSTATE_PCIE_DEVICE(br.dev, PCIEPort), ! 144: VMSTATE_STRUCT(br.dev.exp.aer_log, PCIEPort, 0, vmstate_pcie_aer_log, ! 145: PCIEAERLog), ! 146: VMSTATE_END_OF_LIST() ! 147: } ! 148: }; ! 149: ! 150: static PCIDeviceInfo xio3130_upstream_info = { ! 151: .qdev.name = "x3130-upstream", ! 152: .qdev.desc = "TI X3130 Upstream Port of PCI Express Switch", ! 153: .qdev.size = sizeof(PCIEPort), ! 154: .qdev.reset = xio3130_upstream_reset, ! 155: .qdev.vmsd = &vmstate_xio3130_upstream, ! 156: ! 157: .is_express = 1, ! 158: .is_bridge = 1, ! 159: .config_write = xio3130_upstream_write_config, ! 160: .init = xio3130_upstream_initfn, ! 161: .exit = xio3130_upstream_exitfn, ! 162: ! 163: .qdev.props = (Property[]) { ! 164: DEFINE_PROP_UINT8("port", PCIEPort, port, 0), ! 165: DEFINE_PROP_UINT16("aer_log_max", PCIEPort, br.dev.exp.aer_log.log_max, ! 166: PCIE_AER_LOG_MAX_DEFAULT), ! 167: DEFINE_PROP_END_OF_LIST(), ! 168: } ! 169: }; ! 170: ! 171: static void xio3130_upstream_register(void) ! 172: { ! 173: pci_qdev_register(&xio3130_upstream_info); ! 174: } ! 175: ! 176: device_init(xio3130_upstream_register); ! 177: ! 178: ! 179: /* ! 180: * Local variables: ! 181: * c-indent-level: 4 ! 182: * c-basic-offset: 4 ! 183: * tab-width: 8 ! 184: * indent-tab-mode: nil ! 185: * End: ! 186: */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.