diff mbox series

[RFC,22/23] platforms/qemu: Add fake power control

Message ID 20190403090920.362-23-oohall@gmail.com
State RFC
Headers show
Series [RFC,01/23] platform/firenze-pci: Remove freset | expand

Checks

Context Check Description
snowpatch_ozlabs/apply_patch warning Failed to apply on branch master (050d8165ab05b6d9cdf4bfee42d9776969c77029)
snowpatch_ozlabs/apply_patch fail Failed to apply to any branch

Commit Message

Oliver O'Halloran April 3, 2019, 9:09 a.m. UTC
Adds some power control stubs to the QEMU platform's root complex slots.
This allows us to test the sync and async slot power control paths.

Signed-off-by: Oliver O'Halloran <oohall@gmail.com>
---
 platforms/qemu/qemu.c | 74 ++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 73 insertions(+), 1 deletion(-)
diff mbox series

Patch

diff --git a/platforms/qemu/qemu.c b/platforms/qemu/qemu.c
index 36275ecd50f0..c6db931443d5 100644
--- a/platforms/qemu/qemu.c
+++ b/platforms/qemu/qemu.c
@@ -18,9 +18,81 @@ 
 #include <console.h>
 #include <device.h>
 #include <ipmi.h>
+#include <pci-slot.h>
+#include <pci.h>
+#include <pci-cfg.h>
 
 #include <platforms/astbmc/astbmc.h>
 
+ST_PLUGGABLE(qemu_slot0, "Slot0");
+ST_PLUGGABLE(qemu_slot1, "Slot1");
+ST_PLUGGABLE(qemu_slot2, "Slot2");
+ST_PLUGGABLE(qemu_slot3, "Slot3");
+ST_PLUGGABLE(qemu_slot4, "Slot4");
+ST_PLUGGABLE(qemu_slot5, "Slot5");
+
+static const struct slot_table_entry qemu_phb_table[] = {
+	ST_PHB_ENTRY(0, 0, qemu_slot0),
+	ST_PHB_ENTRY(0, 1, qemu_slot1),
+	ST_PHB_ENTRY(0, 2, qemu_slot2),
+	ST_PHB_ENTRY(0, 3, qemu_slot3),
+	ST_PHB_ENTRY(0, 4, qemu_slot4),
+	ST_PHB_ENTRY(0, 5, qemu_slot5),
+	{ .etype = st_end },
+};
+
+static int64_t qemu_get_power(struct pci_slot *slot, uint8_t *val)
+{
+	*val = slot->power_state;
+	return OPAL_SUCCESS;
+}
+
+static int64_t qemu_set_power_delay(struct pci_slot *slot, uint8_t val)
+{
+	slot->power_state = val;
+
+	PCIERR(slot->phb, 0, "%s: v=%d, ctl_state = %d\n", __func__, val,
+			slot->power_ctl_state);
+	switch (slot->power_ctl_state) {
+	case 0 ... 30:
+		slot->power_ctl_state += 10;
+		break;
+	default:
+		slot->power_ctl_state = 0;
+	}
+
+	return slot->power_ctl_state ? 1 : OPAL_SUCCESS;
+}
+
+static int64_t qemu_set_power_immed(struct pci_slot *slot, uint8_t val)
+{
+	slot->power_state = val;
+	return OPAL_SUCCESS;
+}
+
+static void qemu_get_slot_info(struct phb *phb, struct pci_device *pd)
+{
+	struct pci_slot *slot;
+
+	if (pd) {
+		slot_table_get_slot_info(phb, pd);
+		if (pd->dev_type != PCIE_TYPE_ROOT_PORT)
+			return;
+		slot = pd->slot;
+	} else {
+		slot = phb->slot;
+	}
+
+	/* use the override methods for root ports, and PHB slots */
+	slot->ops.get_power_state = qemu_get_power;
+	slot->ops.poll_link = phb->slot->ops.poll_link;
+
+	if (phb->opal_id & 0x1)
+		slot->ops.set_power_state = qemu_set_power_delay;
+	else
+		slot->ops.set_power_state = qemu_set_power_immed;
+}
+
 static bool bt_device_present;
 
 static bool qemu_probe(void)
@@ -55,7 +127,7 @@  DECLARE_PLATFORM(qemu) = {
 	.name		= "Qemu",
 	.probe		= qemu_probe,
 	.init		= qemu_init,
-	.pci_get_slot_info = slot_table_get_slot_info,
+	.pci_get_slot_info = qemu_get_slot_info,
 	.external_irq   = astbmc_ext_irq_serirq_cpld,
 	.cec_power_down = astbmc_ipmi_power_down,
 	.cec_reboot     = astbmc_ipmi_reboot,