hw/pcie: Factor out PCI Express link register filling common to EP.
Whilst not all link related registers are common between RP / Switch DSP and EP / Switch USP many of them are. Factor that group out to save on duplication when adding EP / Swtich USP configurability. Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com> Message-Id: <20240916173518.1843023-4-Jonathan.Cameron@huawei.com> Reviewed-by: Michael S. Tsirkin <mst@redhat.com> Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
This commit is contained in:
parent
845f94de78
commit
6d1bda9133
@ -105,6 +105,55 @@ pcie_cap_v1_fill(PCIDevice *dev, uint8_t port, uint8_t type, uint8_t version)
|
||||
pci_set_word(cmask + PCI_EXP_LNKSTA, 0);
|
||||
}
|
||||
|
||||
/* Includes setting the target speed default */
|
||||
static void pcie_cap_fill_lnk(uint8_t *exp_cap, PCIExpLinkWidth width,
|
||||
PCIExpLinkSpeed speed)
|
||||
{
|
||||
/* Clear and fill LNKCAP from what was configured above */
|
||||
pci_long_test_and_clear_mask(exp_cap + PCI_EXP_LNKCAP,
|
||||
PCI_EXP_LNKCAP_MLW | PCI_EXP_LNKCAP_SLS);
|
||||
pci_long_test_and_set_mask(exp_cap + PCI_EXP_LNKCAP,
|
||||
QEMU_PCI_EXP_LNKCAP_MLW(width) |
|
||||
QEMU_PCI_EXP_LNKCAP_MLS(speed));
|
||||
|
||||
if (speed > QEMU_PCI_EXP_LNK_2_5GT) {
|
||||
/*
|
||||
* Target Link Speed defaults to the highest link speed supported by
|
||||
* the component. 2.5GT/s devices are permitted to hardwire to zero.
|
||||
*/
|
||||
pci_word_test_and_clear_mask(exp_cap + PCI_EXP_LNKCTL2,
|
||||
PCI_EXP_LNKCTL2_TLS);
|
||||
pci_word_test_and_set_mask(exp_cap + PCI_EXP_LNKCTL2,
|
||||
QEMU_PCI_EXP_LNKCAP_MLS(speed) &
|
||||
PCI_EXP_LNKCTL2_TLS);
|
||||
}
|
||||
|
||||
/*
|
||||
* 2.5 & 5.0GT/s can be fully described by LNKCAP, but 8.0GT/s is
|
||||
* actually a reference to the highest bit supported in this register.
|
||||
* We assume the device supports all link speeds.
|
||||
*/
|
||||
if (speed > QEMU_PCI_EXP_LNK_5GT) {
|
||||
pci_long_test_and_clear_mask(exp_cap + PCI_EXP_LNKCAP2, ~0U);
|
||||
pci_long_test_and_set_mask(exp_cap + PCI_EXP_LNKCAP2,
|
||||
PCI_EXP_LNKCAP2_SLS_2_5GB |
|
||||
PCI_EXP_LNKCAP2_SLS_5_0GB |
|
||||
PCI_EXP_LNKCAP2_SLS_8_0GB);
|
||||
if (speed > QEMU_PCI_EXP_LNK_8GT) {
|
||||
pci_long_test_and_set_mask(exp_cap + PCI_EXP_LNKCAP2,
|
||||
PCI_EXP_LNKCAP2_SLS_16_0GB);
|
||||
}
|
||||
if (speed > QEMU_PCI_EXP_LNK_16GT) {
|
||||
pci_long_test_and_set_mask(exp_cap + PCI_EXP_LNKCAP2,
|
||||
PCI_EXP_LNKCAP2_SLS_32_0GB);
|
||||
}
|
||||
if (speed > QEMU_PCI_EXP_LNK_32GT) {
|
||||
pci_long_test_and_set_mask(exp_cap + PCI_EXP_LNKCAP2,
|
||||
PCI_EXP_LNKCAP2_SLS_64_0GB);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void pcie_cap_fill_slot_lnk(PCIDevice *dev)
|
||||
{
|
||||
PCIESlot *s = (PCIESlot *)object_dynamic_cast(OBJECT(dev), TYPE_PCIE_SLOT);
|
||||
@ -115,13 +164,6 @@ static void pcie_cap_fill_slot_lnk(PCIDevice *dev)
|
||||
return;
|
||||
}
|
||||
|
||||
/* Clear and fill LNKCAP from what was configured above */
|
||||
pci_long_test_and_clear_mask(exp_cap + PCI_EXP_LNKCAP,
|
||||
PCI_EXP_LNKCAP_MLW | PCI_EXP_LNKCAP_SLS);
|
||||
pci_long_test_and_set_mask(exp_cap + PCI_EXP_LNKCAP,
|
||||
QEMU_PCI_EXP_LNKCAP_MLW(s->width) |
|
||||
QEMU_PCI_EXP_LNKCAP_MLS(s->speed));
|
||||
|
||||
/*
|
||||
* Link bandwidth notification is required for all root ports and
|
||||
* downstream ports supporting links wider than x1 or multiple link
|
||||
@ -144,42 +186,9 @@ static void pcie_cap_fill_slot_lnk(PCIDevice *dev)
|
||||
pci_long_test_and_set_mask(exp_cap + PCI_EXP_LNKCAP,
|
||||
PCI_EXP_LNKCAP_DLLLARC);
|
||||
/* the PCI_EXP_LNKSTA_DLLLA will be set in the hotplug function */
|
||||
|
||||
/*
|
||||
* Target Link Speed defaults to the highest link speed supported by
|
||||
* the component. 2.5GT/s devices are permitted to hardwire to zero.
|
||||
*/
|
||||
pci_word_test_and_clear_mask(exp_cap + PCI_EXP_LNKCTL2,
|
||||
PCI_EXP_LNKCTL2_TLS);
|
||||
pci_word_test_and_set_mask(exp_cap + PCI_EXP_LNKCTL2,
|
||||
QEMU_PCI_EXP_LNKCAP_MLS(s->speed) &
|
||||
PCI_EXP_LNKCTL2_TLS);
|
||||
}
|
||||
|
||||
/*
|
||||
* 2.5 & 5.0GT/s can be fully described by LNKCAP, but 8.0GT/s is
|
||||
* actually a reference to the highest bit supported in this register.
|
||||
* We assume the device supports all link speeds.
|
||||
*/
|
||||
if (s->speed > QEMU_PCI_EXP_LNK_5GT) {
|
||||
pci_long_test_and_clear_mask(exp_cap + PCI_EXP_LNKCAP2, ~0U);
|
||||
pci_long_test_and_set_mask(exp_cap + PCI_EXP_LNKCAP2,
|
||||
PCI_EXP_LNKCAP2_SLS_2_5GB |
|
||||
PCI_EXP_LNKCAP2_SLS_5_0GB |
|
||||
PCI_EXP_LNKCAP2_SLS_8_0GB);
|
||||
if (s->speed > QEMU_PCI_EXP_LNK_8GT) {
|
||||
pci_long_test_and_set_mask(exp_cap + PCI_EXP_LNKCAP2,
|
||||
PCI_EXP_LNKCAP2_SLS_16_0GB);
|
||||
}
|
||||
if (s->speed > QEMU_PCI_EXP_LNK_16GT) {
|
||||
pci_long_test_and_set_mask(exp_cap + PCI_EXP_LNKCAP2,
|
||||
PCI_EXP_LNKCAP2_SLS_32_0GB);
|
||||
}
|
||||
if (s->speed > QEMU_PCI_EXP_LNK_32GT) {
|
||||
pci_long_test_and_set_mask(exp_cap + PCI_EXP_LNKCAP2,
|
||||
PCI_EXP_LNKCAP2_SLS_64_0GB);
|
||||
}
|
||||
}
|
||||
pcie_cap_fill_lnk(exp_cap, s->width, s->speed);
|
||||
}
|
||||
|
||||
int pcie_cap_init(PCIDevice *dev, uint8_t offset,
|
||||
|
Loading…
Reference in New Issue
Block a user