diff --git a/hw/occ.c b/hw/occ.c
index 7b502b4..8548513 100644
--- a/hw/occ.c
+++ b/hw/occ.c
@@ -1279,24 +1279,38 @@ static struct fsp_client fsp_occ_client = {
 	.message = fsp_occ_msg,
 };
 
-#define OCB_OCI_OCCMISC		0x6a020
-#define OCB_OCI_OCCMISC_AND	0x6a021
-#define OCB_OCI_OCCMISC_OR	0x6a022
+#define P8_OCB_OCI_OCCMISC		0x6a020
+#define P8_OCB_OCI_OCCMISC_AND		0x6a021
+#define P8_OCB_OCI_OCCMISC_OR		0x6a022
+
+#define P9_OCB_OCI_OCCMISC		0x6c080
+#define P9_OCB_OCI_OCCMISC_CLEAR	0x6c081
+#define P9_OCB_OCI_OCCMISC_OR		0x6c082
+
 #define OCB_OCI_OCIMISC_IRQ		PPC_BIT(0)
 #define OCB_OCI_OCIMISC_IRQ_TMGT	PPC_BIT(1)
 #define OCB_OCI_OCIMISC_IRQ_SLW_TMR	PPC_BIT(14)
 #define OCB_OCI_OCIMISC_IRQ_OPAL_DUMMY	PPC_BIT(15)
-#define OCB_OCI_OCIMISC_MASK		(OCB_OCI_OCIMISC_IRQ_TMGT | \
+
+#define P8_OCB_OCI_OCIMISC_MASK		(OCB_OCI_OCIMISC_IRQ_TMGT | \
 					 OCB_OCI_OCIMISC_IRQ_OPAL_DUMMY | \
 					 OCB_OCI_OCIMISC_IRQ_SLW_TMR)
 
+#define OCB_OCI_OCIMISC_IRQ_I2C		PPC_BIT(2)
+#define OCB_OCI_OCIMISC_IRQ_SHMEM	PPC_BIT(3)
+#define P9_OCB_OCI_OCIMISC_MASK		(OCB_OCI_OCIMISC_IRQ_TMGT | \
+					 OCB_OCI_OCIMISC_IRQ_I2C | \
+					 OCB_OCI_OCIMISC_IRQ_SHMEM | \
+					 OCB_OCI_OCIMISC_IRQ_OPAL_DUMMY)
+
 void occ_send_dummy_interrupt(void)
 {
 	struct psi *psi;
 	struct proc_chip *chip = get_chip(this_cpu()->chip_id);
 
 	/* Emulators and P7 doesn't do this */
-	if (proc_gen != proc_gen_p8 || chip_quirk(QUIRK_NO_OCC_IRQ))
+	if (proc_gen != proc_gen_p8 ||  proc_gen != proc_gen_p9 ||
+	    chip_quirk(QUIRK_NO_OCC_IRQ))
 		return;
 
 	/* Find a functional PSI. This ensures an interrupt even if
@@ -1312,17 +1326,29 @@ void occ_send_dummy_interrupt(void)
 		return;
 	}
 
-	xscom_write(psi->chip_id, OCB_OCI_OCCMISC_OR,
-		    OCB_OCI_OCIMISC_IRQ | OCB_OCI_OCIMISC_IRQ_OPAL_DUMMY);
+	switch (proc_gen) {
+	case proc_gen_p8:
+		xscom_write(psi->chip_id, P8_OCB_OCI_OCCMISC_OR,
+			    OCB_OCI_OCIMISC_IRQ |
+			    OCB_OCI_OCIMISC_IRQ_OPAL_DUMMY);
+		break;
+	case proc_gen_p9:
+		xscom_write(psi->chip_id, P9_OCB_OCI_OCCMISC_OR,
+			    OCB_OCI_OCIMISC_IRQ |
+			    OCB_OCI_OCIMISC_IRQ_OPAL_DUMMY);
+		break;
+	default:
+		break;
+	}
 }
 
-void occ_interrupt(uint32_t chip_id)
+void occ_p8_interrupt(uint32_t chip_id)
 {
 	uint64_t ireg;
 	int64_t rc;
 
 	/* The OCC interrupt is used to mux up to 15 different sources */
-	rc = xscom_read(chip_id, OCB_OCI_OCCMISC, &ireg);
+	rc = xscom_read(chip_id, P8_OCB_OCI_OCCMISC, &ireg);
 	if (rc) {
 		prerror("OCC: Failed to read interrupt status !\n");
 		/* Should we mask it in the XIVR ? */
@@ -1331,7 +1357,7 @@ void occ_interrupt(uint32_t chip_id)
 	prlog(PR_TRACE, "OCC: IRQ received: %04llx\n", ireg >> 48);
 
 	/* Clear the bits */
-	xscom_write(chip_id, OCB_OCI_OCCMISC_AND, ~ireg);
+	xscom_write(chip_id, P8_OCB_OCI_OCCMISC_AND, ~ireg);
 
 	/* Dispatch */
 	if (ireg & OCB_OCI_OCIMISC_IRQ_TMGT)
@@ -1343,9 +1369,43 @@ void occ_interrupt(uint32_t chip_id)
 	 * OCCMISC_AND write. Check if there are any new source bits set,
 	 * and trigger another interrupt if so.
 	 */
-	rc = xscom_read(chip_id, OCB_OCI_OCCMISC, &ireg);
-	if (!rc && (ireg & OCB_OCI_OCIMISC_MASK))
-		xscom_write(chip_id, OCB_OCI_OCCMISC_OR, OCB_OCI_OCIMISC_IRQ);
+	rc = xscom_read(chip_id, P8_OCB_OCI_OCCMISC, &ireg);
+	if (!rc && (ireg & P8_OCB_OCI_OCIMISC_MASK))
+		xscom_write(chip_id, P8_OCB_OCI_OCCMISC_OR,
+			    OCB_OCI_OCIMISC_IRQ);
+}
+
+void occ_p9_interrupt(uint32_t chip_id)
+{
+	u64 ireg;
+	s64 rc;
+
+	/* The OCC interrupt is used to mux up to 15 different sources */
+	rc = xscom_read(chip_id, P9_OCB_OCI_OCCMISC, &ireg);
+	if (rc) {
+		prerror("OCC: Failed to read interrupt status !\n");
+		return;
+	}
+	prlog(PR_TRACE, "OCC: IRQ received: %04llx\n", ireg >> 48);
+
+	/* Clear the bits */
+	xscom_write(chip_id, P9_OCB_OCI_OCCMISC_CLEAR, ireg);
+
+	/* Dispatch */
+	if (ireg & OCB_OCI_OCIMISC_IRQ_TMGT)
+		prd_tmgt_interrupt(chip_id);
+
+	if (ireg & OCB_OCI_OCIMISC_IRQ_SHMEM)
+		occ_throttle_poll(NULL);
+
+	/* We may have masked-out OCB_OCI_OCIMISC_IRQ in the previous
+	 * OCCMISC_AND write. Check if there are any new source bits set,
+	 * and trigger another interrupt if so.
+	 */
+	rc = xscom_read(chip_id, P9_OCB_OCI_OCCMISC, &ireg);
+	if (!rc && (ireg & P9_OCB_OCI_OCIMISC_MASK))
+		xscom_write(chip_id, P9_OCB_OCI_OCCMISC_OR,
+			    OCB_OCI_OCIMISC_IRQ);
 }
 
 void occ_fsp_init(void)
diff --git a/hw/psi.c b/hw/psi.c
index 089f429..cc7db44 100644
--- a/hw/psi.c
+++ b/hw/psi.c
@@ -485,7 +485,7 @@ static void psihb_p8_interrupt(struct irq_source *is, uint32_t isn)
 		psihb_interrupt(is, isn);
 		break;
 	case P8_IRQ_PSI_OCC:
-		occ_interrupt(psi->chip_id);
+		occ_p8_interrupt(psi->chip_id);
 		break;
 	case P8_IRQ_PSI_FSI:
 		printf("PSI: FSI irq received\n");
@@ -572,7 +572,7 @@ static void psihb_p9_interrupt(struct irq_source *is, uint32_t isn)
 		psihb_interrupt(is, isn);
 		break;
 	case P9_PSI_IRQ_OCC:
-		occ_interrupt(psi->chip_id);
+		occ_p9_interrupt(psi->chip_id);
 		break;
 	case P9_PSI_IRQ_FSI:
 		printf("PSI: FSI irq received\n");
diff --git a/include/skiboot.h b/include/skiboot.h
index 8bc767a..2b1f8a5 100644
--- a/include/skiboot.h
+++ b/include/skiboot.h
@@ -254,10 +254,13 @@ enum {
 extern void uart_set_console_policy(int policy);
 extern bool uart_enabled(void);
 
-/* OCC interrupt */
-extern void occ_interrupt(uint32_t chip_id);
+/* OCC interrupt for P8 */
+extern void occ_p8_interrupt(uint32_t chip_id);
 extern void occ_send_dummy_interrupt(void);
 
+/* OCC interrupt for P9 */
+extern void occ_p9_interrupt(uint32_t chip_id);
+
 /* OCC load support */
 extern void occ_poke_load_queue(void);
 
