xref: /qemu/hw/pci-bridge/ioh3420.c (revision 0b8fa32f551e863bb548a11394239239270dd3dc)
18135aeedSIsaku Yamahata /*
28135aeedSIsaku Yamahata  * ioh3420.c
38135aeedSIsaku Yamahata  * Intel X58 north bridge IOH
48135aeedSIsaku Yamahata  * PCI Express root port device id 3420
58135aeedSIsaku Yamahata  *
68135aeedSIsaku Yamahata  * Copyright (c) 2010 Isaku Yamahata <yamahata at valinux co jp>
78135aeedSIsaku Yamahata  *                    VA Linux Systems Japan K.K.
88135aeedSIsaku Yamahata  *
98135aeedSIsaku Yamahata  * This program is free software; you can redistribute it and/or modify
108135aeedSIsaku Yamahata  * it under the terms of the GNU General Public License as published by
118135aeedSIsaku Yamahata  * the Free Software Foundation; either version 2 of the License, or
128135aeedSIsaku Yamahata  * (at your option) any later version.
138135aeedSIsaku Yamahata  *
148135aeedSIsaku Yamahata  * This program is distributed in the hope that it will be useful,
158135aeedSIsaku Yamahata  * but WITHOUT ANY WARRANTY; without even the implied warranty of
168135aeedSIsaku Yamahata  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
178135aeedSIsaku Yamahata  * GNU General Public License for more details.
188135aeedSIsaku Yamahata  *
198135aeedSIsaku Yamahata  * You should have received a copy of the GNU General Public License along
208135aeedSIsaku Yamahata  * with this program; if not, see <http://www.gnu.org/licenses/>.
218135aeedSIsaku Yamahata  */
228135aeedSIsaku Yamahata 
2397d5408fSPeter Maydell #include "qemu/osdep.h"
2483c9f4caSPaolo Bonzini #include "hw/pci/pci_ids.h"
2583c9f4caSPaolo Bonzini #include "hw/pci/msi.h"
2683c9f4caSPaolo Bonzini #include "hw/pci/pcie.h"
27cd1f0ca2SPhilippe Mathieu-Daudé #include "hw/pci/pcie_port.h"
28*0b8fa32fSMarkus Armbruster #include "qemu/module.h"
298135aeedSIsaku Yamahata 
308135aeedSIsaku Yamahata #define PCI_DEVICE_ID_IOH_EPORT         0x3420  /* D0:F0 express mode */
318135aeedSIsaku Yamahata #define PCI_DEVICE_ID_IOH_REV           0x2
328135aeedSIsaku Yamahata #define IOH_EP_SSVID_OFFSET             0x40
338135aeedSIsaku Yamahata #define IOH_EP_SSVID_SVID               PCI_VENDOR_ID_INTEL
348135aeedSIsaku Yamahata #define IOH_EP_SSVID_SSID               0
358135aeedSIsaku Yamahata #define IOH_EP_MSI_OFFSET               0x60
368135aeedSIsaku Yamahata #define IOH_EP_MSI_SUPPORTED_FLAGS      PCI_MSI_FLAGS_MASKBIT
378135aeedSIsaku Yamahata #define IOH_EP_MSI_NR_VECTOR            2
388135aeedSIsaku Yamahata #define IOH_EP_EXP_OFFSET               0x90
398135aeedSIsaku Yamahata #define IOH_EP_AER_OFFSET               0x100
408135aeedSIsaku Yamahata 
4161620c2fSIsaku Yamahata /*
4261620c2fSIsaku Yamahata  * If two MSI vector are allocated, Advanced Error Interrupt Message Number
4361620c2fSIsaku Yamahata  * is 1. otherwise 0.
4461620c2fSIsaku Yamahata  * 17.12.5.10 RPERRSTS,  32:27 bit Advanced Error Interrupt Message Number.
4561620c2fSIsaku Yamahata  */
4661620c2fSIsaku Yamahata static uint8_t ioh3420_aer_vector(const PCIDevice *d)
4761620c2fSIsaku Yamahata {
4861620c2fSIsaku Yamahata     switch (msi_nr_vectors_allocated(d)) {
4961620c2fSIsaku Yamahata     case 1:
5061620c2fSIsaku Yamahata         return 0;
5161620c2fSIsaku Yamahata     case 2:
5261620c2fSIsaku Yamahata         return 1;
5361620c2fSIsaku Yamahata     case 4:
5461620c2fSIsaku Yamahata     case 8:
5561620c2fSIsaku Yamahata     case 16:
5661620c2fSIsaku Yamahata     case 32:
5761620c2fSIsaku Yamahata     default:
5861620c2fSIsaku Yamahata         break;
5961620c2fSIsaku Yamahata     }
6061620c2fSIsaku Yamahata     abort();
6161620c2fSIsaku Yamahata     return 0;
6261620c2fSIsaku Yamahata }
6361620c2fSIsaku Yamahata 
64fed23cb4SMarcel Apfelbaum static int ioh3420_interrupts_init(PCIDevice *d, Error **errp)
6561620c2fSIsaku Yamahata {
668135aeedSIsaku Yamahata     int rc;
6752ea63deSCao jin 
688135aeedSIsaku Yamahata     rc = msi_init(d, IOH_EP_MSI_OFFSET, IOH_EP_MSI_NR_VECTOR,
698135aeedSIsaku Yamahata                   IOH_EP_MSI_SUPPORTED_FLAGS & PCI_MSI_FLAGS_64BIT,
70fed23cb4SMarcel Apfelbaum                   IOH_EP_MSI_SUPPORTED_FLAGS & PCI_MSI_FLAGS_MASKBIT,
7106592d7eSMao Zhongyi                   errp);
728135aeedSIsaku Yamahata     if (rc < 0) {
731108b2f8SCao jin         assert(rc == -ENOTSUP);
748135aeedSIsaku Yamahata     }
7552ea63deSCao jin 
7661620c2fSIsaku Yamahata     return rc;
778135aeedSIsaku Yamahata }
788135aeedSIsaku Yamahata 
79fed23cb4SMarcel Apfelbaum static void ioh3420_interrupts_uninit(PCIDevice *d)
808135aeedSIsaku Yamahata {
8161620c2fSIsaku Yamahata     msi_uninit(d);
828135aeedSIsaku Yamahata }
838135aeedSIsaku Yamahata 
848135aeedSIsaku Yamahata static const VMStateDescription vmstate_ioh3420 = {
858135aeedSIsaku Yamahata     .name = "ioh-3240-express-root-port",
869d6b9db1SPeter Xu     .priority = MIG_PRI_PCI_BUS,
878135aeedSIsaku Yamahata     .version_id = 1,
888135aeedSIsaku Yamahata     .minimum_version_id = 1,
896bde6aaaSMichael S. Tsirkin     .post_load = pcie_cap_slot_post_load,
908135aeedSIsaku Yamahata     .fields = (VMStateField[]) {
9120daa90aSDr. David Alan Gilbert         VMSTATE_PCI_DEVICE(parent_obj.parent_obj.parent_obj, PCIESlot),
92bcb75750SAndreas Färber         VMSTATE_STRUCT(parent_obj.parent_obj.parent_obj.exp.aer_log,
93bcb75750SAndreas Färber                        PCIESlot, 0, vmstate_pcie_aer_log, PCIEAERLog),
948135aeedSIsaku Yamahata         VMSTATE_END_OF_LIST()
958135aeedSIsaku Yamahata     }
968135aeedSIsaku Yamahata };
978135aeedSIsaku Yamahata 
9840021f08SAnthony Liguori static void ioh3420_class_init(ObjectClass *klass, void *data)
9940021f08SAnthony Liguori {
10039bffca2SAnthony Liguori     DeviceClass *dc = DEVICE_CLASS(klass);
10140021f08SAnthony Liguori     PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
102fed23cb4SMarcel Apfelbaum     PCIERootPortClass *rpc = PCIE_ROOT_PORT_CLASS(klass);
10340021f08SAnthony Liguori 
10440021f08SAnthony Liguori     k->vendor_id = PCI_VENDOR_ID_INTEL;
10540021f08SAnthony Liguori     k->device_id = PCI_DEVICE_ID_IOH_EPORT;
10640021f08SAnthony Liguori     k->revision = PCI_DEVICE_ID_IOH_REV;
10739bffca2SAnthony Liguori     dc->desc = "Intel IOH device id 3420 PCIE Root Port";
10839bffca2SAnthony Liguori     dc->vmsd = &vmstate_ioh3420;
109fed23cb4SMarcel Apfelbaum     rpc->aer_vector = ioh3420_aer_vector;
110fed23cb4SMarcel Apfelbaum     rpc->interrupts_init = ioh3420_interrupts_init;
111fed23cb4SMarcel Apfelbaum     rpc->interrupts_uninit = ioh3420_interrupts_uninit;
112fed23cb4SMarcel Apfelbaum     rpc->exp_offset = IOH_EP_EXP_OFFSET;
113fed23cb4SMarcel Apfelbaum     rpc->aer_offset = IOH_EP_AER_OFFSET;
114fed23cb4SMarcel Apfelbaum     rpc->ssvid_offset = IOH_EP_SSVID_OFFSET;
115fed23cb4SMarcel Apfelbaum     rpc->ssid = IOH_EP_SSVID_SSID;
1168135aeedSIsaku Yamahata }
11740021f08SAnthony Liguori 
1188c43a6f0SAndreas Färber static const TypeInfo ioh3420_info = {
11940021f08SAnthony Liguori     .name          = "ioh3420",
120fed23cb4SMarcel Apfelbaum     .parent        = TYPE_PCIE_ROOT_PORT,
12140021f08SAnthony Liguori     .class_init    = ioh3420_class_init,
1228135aeedSIsaku Yamahata };
1238135aeedSIsaku Yamahata 
12483f7d43aSAndreas Färber static void ioh3420_register_types(void)
1258135aeedSIsaku Yamahata {
12639bffca2SAnthony Liguori     type_register_static(&ioh3420_info);
1278135aeedSIsaku Yamahata }
1288135aeedSIsaku Yamahata 
12983f7d43aSAndreas Färber type_init(ioh3420_register_types)
130