aboutsummaryrefslogtreecommitdiff
path: root/platforms
diff options
context:
space:
mode:
Diffstat (limited to 'platforms')
-rw-r--r--platforms/astbmc/witherspoon.c94
1 files changed, 94 insertions, 0 deletions
diff --git a/platforms/astbmc/witherspoon.c b/platforms/astbmc/witherspoon.c
index abaa7c9..4604986 100644
--- a/platforms/astbmc/witherspoon.c
+++ b/platforms/astbmc/witherspoon.c
@@ -21,9 +21,17 @@
#include <ipmi.h>
#include <psi.h>
#include <npu-regs.h>
+#include <xscom.h>
+#include <xscom-p9-regs.h>
+#include <timebase.h>
+#include <pci.h>
+#include <pci-slot.h>
+#include <phb4.h>
#include "astbmc.h"
+#define PHB4_SHARED_SLOT_IDX_WITHERSPOON 3
+
static bool witherspoon_probe(void)
{
if (!dt_node_is_compatible(dt_root, "ibm,witherspoon"))
@@ -38,10 +46,96 @@ static bool witherspoon_probe(void)
return true;
}
+static void phb4_activate_shared_slot_witherspoon(struct proc_chip *chip)
+{
+ uint64_t val;
+
+ /*
+ * Shared slot activation is done by raising a GPIO line on the
+ * chip with the secondary slot. It will somehow activate the
+ * sideband signals between the slots.
+ * Need to wait 100us for stability.
+ */
+ xscom_read(chip->id, P9_GPIO_DATA_OUT_ENABLE, &val);
+ val |= PPC_BIT(2);
+ xscom_write(chip->id, P9_GPIO_DATA_OUT_ENABLE, val);
+
+ xscom_read(chip->id, P9_GPIO_DATA_OUT, &val);
+ val |= PPC_BIT(2);
+ xscom_write(chip->id, P9_GPIO_DATA_OUT, val);
+ time_wait_us(100);
+ prlog(PR_INFO, "Shared PCI slot activated\n");
+}
+
+static void phb4_pre_pci_fixup_witherspoon(void)
+{
+ struct pci_slot *slot0, *slot1;
+ struct proc_chip *chip0, *chip1;
+ uint8_t p0 = 0, p1 = 0;
+
+ /*
+ * Detect if a x16 card is present on the shared slot and
+ * do some extra configuration if it is.
+ *
+ * The shared slot, a.k.a "Slot 2" in the documentation, is
+ * connected to PEC2 phb index 3 on both chips. From skiboot,
+ * it looks like two x8 slots, each with its own presence bit.
+ *
+ * Here is the matrix of possibilities for the presence bits:
+ *
+ * slot0 presence slot1 presence
+ * 0 0 => no card
+ * 1 0 => x8 or less card detected
+ * 1 1 => x16 card detected
+ * 0 1 => invalid combination
+ *
+ * We only act if a x16 card is detected ('1 1' combination above).
+ *
+ * One issue is that we don't really know if it is a
+ * shared-slot-compatible card (such as Mellanox CX5) or
+ * a 'normal' x16 PCI card. We activate the shared slot in both cases,
+ * as it doesn't seem to hurt.
+ *
+ * If the card is a normal x16 PCI card, the link won't train on the
+ * second slot (nothing to do with the shared slot activation), the
+ * procedure will timeout, thus adding some delay to the boot time.
+ * Therefore the recommendation is that we shouldn't use a normal
+ * x16 card on the shared slot of a witherspoon.
+ *
+ * Plugging a x8 or less adapter on the shared slot should work
+ * like any other physical slot.
+ */
+ chip0 = next_chip(NULL);
+ chip1 = next_chip(chip0);
+ if (!chip1 || next_chip(chip1)) {
+ prlog(PR_WARNING,
+ "Unexpected number of chips, skipping shared slot detection\n");
+ return;
+ }
+ slot0 = pci_slot_find(phb4_get_opal_id(chip0->id,
+ PHB4_SHARED_SLOT_IDX_WITHERSPOON));
+ slot1 = pci_slot_find(phb4_get_opal_id(chip1->id,
+ PHB4_SHARED_SLOT_IDX_WITHERSPOON));
+ if (slot0 && slot1) {
+ if (slot0->ops.get_presence_state)
+ slot0->ops.get_presence_state(slot0, &p0);
+ if (slot1->ops.get_presence_state)
+ slot1->ops.get_presence_state(slot1, &p1);
+ if (p0 == 1 && p1 == 1)
+ phb4_activate_shared_slot_witherspoon(chip1);
+ }
+}
+
+static void witherspoon_pre_pci_fixup(void)
+{
+ phb4_pre_pci_fixup_witherspoon();
+}
+
DECLARE_PLATFORM(witherspoon_platform) = {
.name = "Witherspoon",
.probe = witherspoon_probe,
.init = astbmc_init,
+ .pre_pci_fixup = witherspoon_pre_pci_fixup,
.start_preload_resource = flash_start_preload_resource,
.resource_loaded = flash_resource_loaded,
.bmc = NULL, /* FIXME: Add openBMC */