diff options
Diffstat (limited to 'platforms')
-rw-r--r-- | platforms/astbmc/witherspoon.c | 94 |
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 */ |