Commit e5fd1eb0 authored by Mark Cave-Ayland's avatar Mark Cave-Ayland
Browse files

apb: add busA qdev property to PBM PCI bridge



As future sun4u PCI topologies place the ebus containing the in-built devices
behind a PCI bridge, add a busA property to the PBM PCI bridge that is then
used to allow IO accesses by default.

This allows early fw_cfg/NVRAM/serial access to occur even before OpenBIOS
has had a chance to configure the PCI bridges.

Signed-off-by: default avatarMark Cave-Ayland <mark.cave-ayland@ilande.co.uk>
parent b2f9005a
Loading
Loading
Loading
Loading
+37 −7
Original line number Diff line number Diff line
@@ -155,6 +155,18 @@ typedef struct APBState {
    unsigned int nr_resets;
} APBState;

#define TYPE_PBM_PCI_BRIDGE "pbm-bridge"
#define PBM_PCI_BRIDGE(obj) \
    OBJECT_CHECK(PBMPCIBridge, (obj), TYPE_PBM_PCI_BRIDGE)

typedef struct PBMPCIBridge {
    /*< private >*/
    PCIBridge parent_obj;

    /* Is this busA with in-built devices (ebus)? */
    bool busA;
} PBMPCIBridge;

static inline void pbm_set_request(APBState *s, unsigned int irq_num)
{
    APB_DPRINTF("%s: request irq %d\n", __func__, irq_num);
@@ -632,8 +644,6 @@ static void pci_apb_set_irq(void *opaque, int irq_num, int level)

static void apb_pci_bridge_realize(PCIDevice *dev, Error **errp)
{
    pci_bridge_initfn(dev, TYPE_PCI_BUS);

    /*
     * command register:
     * According to PCI bridge spec, after reset
@@ -643,11 +653,23 @@ static void apb_pci_bridge_realize(PCIDevice *dev, Error **errp)
     *   the reset value should be zero unless the boot pin is tied high
     *   (which is true) and thus it should be PCI_COMMAND_MEMORY.
     */
    pci_set_word(dev->config + PCI_COMMAND,
                 PCI_COMMAND_MEMORY);
    uint16_t cmd = PCI_COMMAND_MEMORY;
    PBMPCIBridge *br = PBM_PCI_BRIDGE(dev);

    pci_bridge_initfn(dev, TYPE_PCI_BUS);

    /* If initialising busA, ensure that we allow IO transactions so that
       we get the early serial console until OpenBIOS configures the bridge */
    if (br->busA) {
        cmd |= PCI_COMMAND_IO;
    }

    pci_set_word(dev->config + PCI_COMMAND, cmd);
    pci_set_word(dev->config + PCI_STATUS,
                 PCI_STATUS_FAST_BACK | PCI_STATUS_66MHZ |
                 PCI_STATUS_DEVSEL_MEDIUM);

    pci_bridge_update_mappings(PCI_BRIDGE(br));
}

PCIBus *pci_apb_init(hwaddr special_base,
@@ -701,16 +723,17 @@ PCIBus *pci_apb_init(hwaddr special_base,

    /* APB secondary busses */
    pci_dev = pci_create_multifunction(phb->bus, PCI_DEVFN(1, 0), true,
                                   "pbm-bridge");
                                   TYPE_PBM_PCI_BRIDGE);
    br = PCI_BRIDGE(pci_dev);
    pci_bridge_map_irq(br, "pciB", pci_apb_map_irq);
    qdev_init_nofail(&pci_dev->qdev);
    *busB = pci_bridge_get_sec_bus(br);

    pci_dev = pci_create_multifunction(phb->bus, PCI_DEVFN(1, 1), true,
                                   "pbm-bridge");
                                   TYPE_PBM_PCI_BRIDGE);
    br = PCI_BRIDGE(pci_dev);
    pci_bridge_map_irq(br, "pciA", pci_apb_map_irq);
    qdev_prop_set_bit(DEVICE(pci_dev), "busA", true);
    qdev_init_nofail(&pci_dev->qdev);
    *busA = pci_bridge_get_sec_bus(br);

@@ -832,6 +855,11 @@ static const TypeInfo pbm_host_info = {
    .class_init    = pbm_host_class_init,
};

static Property pbm_pci_properties[] = {
    DEFINE_PROP_BOOL("busA", PBMPCIBridge, busA, false),
    DEFINE_PROP_END_OF_LIST(),
};

static void pbm_pci_bridge_class_init(ObjectClass *klass, void *data)
{
    DeviceClass *dc = DEVICE_CLASS(klass);
@@ -847,12 +875,14 @@ static void pbm_pci_bridge_class_init(ObjectClass *klass, void *data)
    set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories);
    dc->reset = pci_bridge_reset;
    dc->vmsd = &vmstate_pci_device;
    dc->props = pbm_pci_properties;
}

static const TypeInfo pbm_pci_bridge_info = {
    .name          = "pbm-bridge",
    .name          = TYPE_PBM_PCI_BRIDGE,
    .parent        = TYPE_PCI_BRIDGE,
    .class_init    = pbm_pci_bridge_class_init,
    .instance_size = sizeof(PBMPCIBridge),
};

static void pbm_iommu_memory_region_class_init(ObjectClass *klass, void *data)