diff --git a/platforms/ibm-fsp/firenze-pci.c b/platforms/ibm-fsp/firenze-pci.c
index 5fbbc2ff..08467632 100644
--- a/platforms/ibm-fsp/firenze-pci.c
+++ b/platforms/ibm-fsp/firenze-pci.c
@@ -969,7 +969,10 @@ void firenze_pci_get_slot_info(struct phb *phb, struct pci_device *pd)
 	s = lxvpd_get_slot(slot);
 	if (s) {
 		lxvpd_extract_info(slot, s);
-		firenze_pci_slot_init(slot);
+		if (proc_gen == proc_gen_p9)
+			zz_pci_slot_init(slot);
+		else
+			firenze_pci_slot_init(slot);
 	}
 }
 
diff --git a/platforms/ibm-fsp/ibm-fsp.h b/platforms/ibm-fsp/ibm-fsp.h
index bb191645..b5b61b56 100644
--- a/platforms/ibm-fsp/ibm-fsp.h
+++ b/platforms/ibm-fsp/ibm-fsp.h
@@ -31,6 +31,7 @@ extern void firenze_pci_get_slot_info(struct phb *phb,
 				      struct pci_device *pd);
 extern void firenze_pci_add_loc_code(struct dt_node *np,
 				      struct pci_device *pd);
+void zz_pci_slot_init(struct pci_slot *slot);
 
 /* VPD support */
 void vpd_iohub_load(struct dt_node *hub_node);
diff --git a/platforms/ibm-fsp/zz.c b/platforms/ibm-fsp/zz.c
index 493d6030..8ce3e936 100644
--- a/platforms/ibm-fsp/zz.c
+++ b/platforms/ibm-fsp/zz.c
@@ -6,6 +6,7 @@
 #include <fsp.h>
 #include <pci.h>
 #include <pci-cfg.h>
+#include <pci-slot.h>
 #include <chip.h>
 #include <i2c.h>
 #include <timebase.h>
@@ -141,6 +142,193 @@ static void add_opencapi_dt_nodes(void)
 	}
 }
 
+#define UCD_GPIO_SELECT 0xFA
+#define UCD_GPIO_CONFIG 0xFB
+
+struct hp_controller {
+	struct lock lock;
+	struct i2c_request req;
+};
+
+struct hp_controller ucd;
+
+struct zz_pci_slot_info {
+	uint8_t		index;
+	const char	*label;
+	uint8_t		slave_addr;
+	uint8_t		enable_port;
+	uint8_t		pgood_port;
+};
+
+static struct zz_pci_slot_info zz_pci_slots[] = {
+	/* UCD 9090-0 */
+	{ 0x06,  "C2", 0xC8, 0, 18 },
+	{ 0x07,  "C3", 0xC8, 4, 22 },
+	{ 0x08,  "C4", 0xC8, 5, 15 },
+	{ 0x09,  "C5", 0xC8, 6, 16 },
+	{ 0x0A,  "C6", 0xC8, 7, 17 },
+	/* UCD 90120A-0 */
+	{ 0x0B,  "C7", 0xD0, 0, 18 },
+	{ 0x0C,  "C8", 0xD0, 1, 19 },
+	{ 0x0D,  "C9", 0xD0, 4, 20 },
+	{ 0x0E, "C10", 0xD0, 5, 21 },
+	{ 0x0F, "C11", 0xD0, 6, 24 },
+	{ 0x10, "C12", 0xD0, 7, 25 },
+};
+
+static struct zz_pci_slot_info *zz_get_slot_info(struct lxvpd_pci_slot *s)
+{
+	for (int i = 0; i < ARRAY_SIZE(zz_pci_slots); i++) {
+		if (zz_pci_slots[i].index == s->slot_index &&
+		    !strcmp(zz_pci_slots[i].label, s->label)) {
+			return &zz_pci_slots[i];
+		}
+	}
+	return NULL;
+}
+
+static void hp_controller_init(struct hp_controller *hpc)
+{
+	init_lock(&hpc->lock);
+	hpc->req.offset = 0;
+	hpc->req.offset_bytes = 1;
+	hpc->req.rw_len = 1;
+	hpc->req.timeout = 100;
+	hpc->req.bus = p8_i2c_find_bus_by_port(0, 2, 1);
+	if (!hpc->req.bus) {
+		prerror("PLAT: Unable to find PCI power controller I2C bus\n");
+		return;
+	}
+}
+
+static int64_t __ucd_op(struct hp_controller *hpc, enum i2c_operation op,
+			uint32_t addr, uint8_t port, uint8_t *state)
+{
+	int64_t rc;
+
+	if (!hpc->req.bus)
+		return OPAL_HARDWARE;
+
+	hpc->req.op = SMBUS_WRITE;
+	hpc->req.dev_addr = addr >> 1;
+	hpc->req.offset = UCD_GPIO_SELECT;
+	hpc->req.rw_buf = &port;
+	rc = i2c_request_sync(&hpc->req);
+	if (rc)
+		return rc;
+
+	hpc->req.op = op;
+	hpc->req.dev_addr = addr >> 1;
+	hpc->req.offset = UCD_GPIO_CONFIG;
+	hpc->req.rw_buf = state;
+	return i2c_request_sync(&hpc->req);
+}
+
+static int64_t ucd_read(struct hp_controller *hpc, uint32_t addr,
+			uint8_t port, uint8_t *state)
+{
+	return __ucd_op(hpc, SMBUS_READ, addr, port, state);
+}
+
+static int64_t ucd_write(struct hp_controller *hpc, uint32_t addr,
+			 uint8_t port, uint8_t state)
+{
+	return __ucd_op(hpc, SMBUS_WRITE, addr, port, &state);
+}
+
+static int64_t hp_controller_read_state(struct hp_controller *hpc,
+					struct zz_pci_slot_info *info,
+					uint8_t *val)
+{
+	uint8_t enable, pgood;
+	int64_t rc;
+
+	lock(&hpc->lock);
+
+	rc = ucd_read(hpc, info->slave_addr, info->pgood_port, &pgood);
+	if (rc)
+		goto unlock_err;
+
+	rc = ucd_read(hpc, info->slave_addr, info->enable_port, &enable);
+	if (rc)
+		goto unlock_err;
+
+	unlock(&hpc->lock);
+
+	*val = ((enable & 0xE) == 0xE) && ((pgood & 0xE) == 0x8);
+	return OPAL_SUCCESS;
+
+unlock_err:
+	unlock(&hpc->lock);
+	prerror("PLAT: Can't read the state of PCI slot %s, rc=%lld\n",
+		info->label, rc);
+	return rc;
+}
+
+static int64_t hp_controller_write_state(struct hp_controller *hpc,
+					 struct zz_pci_slot_info *info,
+					 uint8_t val)
+{
+	uint8_t enable;
+	int64_t rc;
+
+	if (val == PCI_SLOT_POWER_ON)
+		enable = 0x7;
+	else
+		enable = 0x3;
+
+	lock(&hpc->lock);
+	rc = ucd_write(hpc, info->slave_addr, info->enable_port, enable);
+	unlock(&hpc->lock);
+	return rc;
+}
+
+static int64_t zz_pci_slot_get_power_state(struct pci_slot *slot, uint8_t *val)
+{
+	struct lxvpd_pci_slot *s = slot->data;
+	struct zz_pci_slot_info *info = NULL;
+
+	info = zz_get_slot_info(s);
+	if (!info)
+		return OPAL_PARAMETER;
+
+	return hp_controller_read_state(&ucd, info, val);
+}
+
+static int64_t zz_pci_slot_set_power_state(struct pci_slot *slot,
+					   uint8_t val)
+{
+	struct lxvpd_pci_slot *s = slot->data;
+	struct zz_pci_slot_info *info = NULL;
+
+	if (val != PCI_SLOT_POWER_OFF && val != PCI_SLOT_POWER_ON)
+		return OPAL_PARAMETER;
+
+	info = zz_get_slot_info(s);
+	if (!info)
+		return OPAL_PARAMETER;
+
+	slot->power_state = val;
+	return hp_controller_write_state(&ucd, info, val);
+}
+
+void zz_pci_slot_init(struct pci_slot *slot)
+{
+	struct lxvpd_pci_slot *s = slot->data;
+	struct zz_pci_slot_info *info;
+
+	slot->ops.add_properties = lxvpd_add_slot_properties;
+
+	info = zz_get_slot_info(s);
+	if (!info)
+		return; /* Slot doesn't support power management */
+
+	prlog(PR_INFO, "PLAT: PCI slot %s supports power management\n",
+	      info->label);
+	slot->ops.get_power_state = zz_pci_slot_get_power_state;
+	slot->ops.set_power_state = zz_pci_slot_set_power_state;
+}
+
 static bool zz_probe(void)
 {
 	/* FIXME: make this neater when the dust settles */
@@ -179,6 +367,7 @@ static void zz_init(void)
 {
 	ibm_fsp_init();
 	hservice_fsp_init();
+	hp_controller_init(&ucd);
 }
 
 DECLARE_PLATFORM(zz) = {
