aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--hw/phb4.c35
-rw-r--r--include/phb4-regs.h2
2 files changed, 36 insertions, 1 deletions
diff --git a/hw/phb4.c b/hw/phb4.c
index 9bc8d47..e30339f 100644
--- a/hw/phb4.c
+++ b/hw/phb4.c
@@ -3072,6 +3072,18 @@ static void phb4_assert_perst(struct pci_slot *slot, bool assert)
phb4_pcicfg_write16(&p->phb, 0, p->ecap + PCICAP_EXP_LCTL, linkctl);
}
+static void set_sys_disable_detect(struct phb4 *p, bool set)
+{
+ uint64_t val;
+
+ val = in_be64(p->regs + PHB_PCIE_DLP_TRAIN_CTL);
+ if (set)
+ val |= PHB_PCIE_DLP_SYS_DISABLEDETECT;
+ else
+ val &= ~PHB_PCIE_DLP_SYS_DISABLEDETECT;
+ out_be64(p->regs + PHB_PCIE_DLP_TRAIN_CTL, val);
+}
+
static int64_t phb4_hreset(struct pci_slot *slot)
{
struct phb4 *p = phb_to_phb4(slot->phb);
@@ -3088,6 +3100,12 @@ static int64_t phb4_hreset(struct pci_slot *slot)
return OPAL_SUCCESS;
}
+ /* circumvention for HW551382 */
+ if (is_phb5()) {
+ PHBINF(p, "HRESET: Workaround for HW551382\n");
+ set_sys_disable_detect(p, true);
+ }
+
PHBDBG(p, "HRESET: Prepare for link down\n");
phb4_prepare_link_change(slot, false);
/* fall through */
@@ -3120,6 +3138,8 @@ static int64_t phb4_hreset(struct pci_slot *slot)
pci_slot_set_state(slot, PHB4_SLOT_HRESET_DELAY2);
return pci_slot_set_sm_timeout(slot, secs_to_tb(1));
case PHB4_SLOT_HRESET_DELAY2:
+ if (is_phb5())
+ set_sys_disable_detect(p, false);
pci_slot_set_state(slot, PHB4_SLOT_LINK_START);
return slot->ops.poll_link(slot);
default:
@@ -3146,6 +3166,12 @@ static int64_t phb4_freset(struct pci_slot *slot)
phb4_prepare_link_change(slot, false);
if (!p->skip_perst) {
+ /* circumvention for HW551382 */
+ if (is_phb5()) {
+ PHBINF(p, "FRESET: Workaround for HW551382\n");
+ set_sys_disable_detect(p, true);
+ }
+
PHBDBG(p, "FRESET: Assert\n");
phb4_assert_perst(slot, true);
pci_slot_set_state(slot, PHB4_SLOT_FRESET_ASSERT_DELAY);
@@ -3169,6 +3195,9 @@ static int64_t phb4_freset(struct pci_slot *slot)
if (pci_tracing)
phb4_link_trace(p, PHB_PCIE_DLP_LTSSM_L0, 3000);
+ if (is_phb5())
+ set_sys_disable_detect(p, false);
+
pci_slot_set_state(slot, PHB4_SLOT_LINK_START);
return slot->ops.poll_link(slot);
default:
@@ -3398,6 +3427,12 @@ static int64_t phb4_creset(struct pci_slot *slot)
p->creset_start_time = mftb();
+ /* circumvention for HW551382 */
+ if (is_phb5()) {
+ PHBINF(p, "CRESET: Workaround for HW551382\n");
+ set_sys_disable_detect(p, true);
+ }
+
phb4_prepare_link_change(slot, false);
/* Clear error inject register, preventing recursive errors */
xscom_write(p->chip_id, p->pe_xscom + 0x2, 0x0);
diff --git a/include/phb4-regs.h b/include/phb4-regs.h
index 8ab78c3..85d2cf2 100644
--- a/include/phb4-regs.h
+++ b/include/phb4-regs.h
@@ -275,7 +275,7 @@
#define PHB_PCIE_DLP_DL_PGRESET PPC_BIT(22)
#define PHB_PCIE_DLP_TRAINING PPC_BIT(20)
#define PHB_PCIE_DLP_INBAND_PRESENCE PPC_BIT(19)
-
+#define PHB_PCIE_DLP_SYS_DISABLEDETECT PPC_BIT(12)
#define PHB_PCIE_DLP_CTL 0x1A78
#define PHB_PCIE_DLP_CTL_BYPASS_PH2 PPC_BIT(4)
#define PHB_PCIE_DLP_CTL_BYPASS_PH3 PPC_BIT(5)