Blame SOURCES/opal-prd-781b10633945df32fa2292ee8b196c74f8ef2c7c.patch

f021ee
diff -up skiboot-5.9/external/opal-prd/opal-prd.c.me skiboot-5.9/external/opal-prd/opal-prd.c
f021ee
--- skiboot-5.9/external/opal-prd/opal-prd.c.me	2018-01-22 11:44:50.353992246 +0100
f021ee
+++ skiboot-5.9/external/opal-prd/opal-prd.c	2018-01-22 11:44:50.362991906 +0100
f021ee
@@ -303,6 +303,8 @@ extern int call_sbe_message_passing(uint
f021ee
 extern uint64_t call_get_ipoll_events(void);
f021ee
 extern int call_firmware_notify(uint64_t len, void *data);
f021ee
 extern int call_reset_pm_complex(uint64_t chip);
f021ee
+extern int call_load_pm_complex(u64 chip, u64 homer, u64 occ_common, u32 mode);
f021ee
+extern int call_start_pm_complex(u64 chip);
f021ee
 
f021ee
 void hservice_puts(const char *str)
f021ee
 {
f021ee
@@ -1418,6 +1420,61 @@ static int handle_msg_occ_error(struct o
f021ee
 	return 0;
f021ee
 }
f021ee
 
f021ee
+static int pm_complex_load_start(void)
f021ee
+{
f021ee
+	struct prd_range *range;
f021ee
+	u64 homer, occ_common;
f021ee
+	int rc = -1, i;
f021ee
+
f021ee
+	if (!hservice_runtime->load_pm_complex) {
f021ee
+		pr_log_nocall("load_pm_complex");
f021ee
+		return rc;
f021ee
+	}
f021ee
+
f021ee
+	if (!hservice_runtime->start_pm_complex) {
f021ee
+		pr_log_nocall("start_pm_complex");
f021ee
+		return rc;
f021ee
+	}
f021ee
+
f021ee
+	range = find_range("ibm,occ-common-area", 0);
f021ee
+	if (!range) {
f021ee
+		pr_log(LOG_ERR, "PM: ibm,occ-common-area not found");
f021ee
+		return rc;
f021ee
+	}
f021ee
+	occ_common = range->physaddr;
f021ee
+
f021ee
+	for (i = 0; i < nr_chips; i++) {
f021ee
+		range = find_range("ibm,homer-image", chips[i]);
f021ee
+		if (!range) {
f021ee
+			pr_log(LOG_ERR, "PM: ibm,homer-image not found 0x%lx",
f021ee
+			       chips[i]);
f021ee
+			return -1;
f021ee
+		}
f021ee
+		homer = range->physaddr;
f021ee
+
f021ee
+		pr_debug("PM: calling load_pm_complex(0x%lx, 0x%lx, 0x%lx, LOAD)",
f021ee
+			 chips[i], homer, occ_common);
f021ee
+		rc = call_load_pm_complex(chips[i], homer, occ_common, 0);
f021ee
+		if (rc) {
f021ee
+			pr_log(LOG_ERR, "PM: Failed load_pm_complex(0x%lx) %m",
f021ee
+			       chips[i]);
f021ee
+			return rc;
f021ee
+		}
f021ee
+	}
f021ee
+
f021ee
+	for (i = 0; i < nr_chips; i++) {
f021ee
+		pr_debug("PM: calling start_pm_complex(0x%lx)", chips[i]);
f021ee
+		rc = call_start_pm_complex(chips[i]);
f021ee
+		if (rc) {
f021ee
+			pr_log(LOG_ERR, "PM: Failed start_pm_complex(0x%lx): %m",
f021ee
+			       chips[i]);
f021ee
+			return rc;
f021ee
+		}
f021ee
+	}
f021ee
+
f021ee
+	return rc;
f021ee
+}
f021ee
+
f021ee
 static int pm_complex_reset(uint64_t chip)
f021ee
 {
f021ee
 	int rc;
f021ee
@@ -1427,13 +1484,24 @@ static int pm_complex_reset(uint64_t chi
f021ee
 	 * BMC system -> process_occ_reset
f021ee
 	 */
f021ee
 	if (is_fsp_system()) {
f021ee
+		int i;
f021ee
+
f021ee
 		if (!hservice_runtime->reset_pm_complex) {
f021ee
 			pr_log_nocall("reset_pm_complex");
f021ee
 			return -1;
f021ee
 		}
f021ee
 
f021ee
-		pr_debug("PM: calling pm_complex_reset(%ld)", chip);
f021ee
-		rc = call_reset_pm_complex(chip);
f021ee
+		for (i = 0; i < nr_chips; i++) {
f021ee
+			pr_debug("PM: calling pm_complex_reset(%ld)", chips[i]);
f021ee
+			rc = call_reset_pm_complex(chip);
f021ee
+			if (rc) {
f021ee
+				pr_log(LOG_ERR, "PM: Failed pm_complex_reset(%ld): %m",
f021ee
+				       chips[i]);
f021ee
+				return rc;
f021ee
+			}
f021ee
+		}
f021ee
+
f021ee
+		rc = pm_complex_load_start();
f021ee
 	} else {
f021ee
 		if (!hservice_runtime->process_occ_reset) {
f021ee
 			pr_log_nocall("process_occ_reset");
f021ee
@@ -1539,6 +1607,27 @@ static int handle_msg_fsp_occ_reset(stru
f021ee
 	return rc;
f021ee
 }
f021ee
 
f021ee
+static int handle_msg_fsp_occ_load_start(struct opal_prd_msg *msg)
f021ee
+{
f021ee
+	struct opal_prd_msg omsg;
f021ee
+	int rc;
f021ee
+
f021ee
+	pr_debug("FW: FSP requested OCC load/start");
f021ee
+	rc = pm_complex_load_start();
f021ee
+
f021ee
+	omsg.hdr.type = OPAL_PRD_MSG_TYPE_FSP_OCC_LOAD_START_STATUS;
f021ee
+	omsg.hdr.size = htobe16(sizeof(omsg));
f021ee
+	omsg.fsp_occ_reset_status.chip = msg->occ_reset.chip;
f021ee
+	omsg.fsp_occ_reset_status.status = htobe64(rc);
f021ee
+
f021ee
+	if (write(ctx->fd, &omsg, sizeof(omsg)) != sizeof(omsg)) {
f021ee
+		pr_log(LOG_ERR, "FW: Failed to send FSP_OCC_LOAD_START_STATUS msg: %m");
f021ee
+		return -1;
f021ee
+	}
f021ee
+
f021ee
+	return rc;
f021ee
+}
f021ee
+
f021ee
 static int handle_prd_msg(struct opal_prd_ctx *ctx, struct opal_prd_msg *msg)
f021ee
 {
f021ee
 	int rc = -1;
f021ee
@@ -1562,6 +1651,9 @@ static int handle_prd_msg(struct opal_pr
f021ee
 	case OPAL_PRD_MSG_TYPE_FSP_OCC_RESET:
f021ee
 		rc = handle_msg_fsp_occ_reset(msg);
f021ee
 		break;
f021ee
+	case OPAL_PRD_MSG_TYPE_FSP_OCC_LOAD_START:
f021ee
+		rc = handle_msg_fsp_occ_load_start(msg);
f021ee
+		break;
f021ee
 	default:
f021ee
 		pr_log(LOG_WARNING, "Invalid incoming message type 0x%x",
f021ee
 				msg->hdr.type);
f021ee
diff -up skiboot-5.9/hw/occ.c.me skiboot-5.9/hw/occ.c
f021ee
--- skiboot-5.9/hw/occ.c.me	2018-01-22 11:44:50.355992171 +0100
f021ee
+++ skiboot-5.9/hw/occ.c	2018-01-22 11:44:50.362991906 +0100
f021ee
@@ -1748,6 +1748,8 @@ void occ_poke_load_queue(void)
f021ee
 	}
f021ee
 }
f021ee
 
f021ee
+static u32 last_seq_id;
f021ee
+static bool in_ipl = true;
f021ee
 static void occ_do_load(u8 scope, u32 dbob_id __unused, u32 seq_id)
f021ee
 {
f021ee
 	struct fsp_msg *rsp;
f021ee
@@ -1780,15 +1782,25 @@ static void occ_do_load(u8 scope, u32 db
f021ee
 		return;
f021ee
 
f021ee
 	if (proc_gen == proc_gen_p9) {
f021ee
-		rc = -ENOMEM;
f021ee
-		/* OCC is pre-loaded in P9, so send SUCCESS to FSP */
f021ee
-		rsp = fsp_mkmsg(FSP_CMD_LOAD_OCC_STAT, 2, 0, seq_id);
f021ee
-		if (rsp)
f021ee
+		if (in_ipl) {
f021ee
+			/* OCC is pre-loaded in P9, so send SUCCESS to FSP */
f021ee
+			rsp = fsp_mkmsg(FSP_CMD_LOAD_OCC_STAT, 2, 0, seq_id);
f021ee
+			if (!rsp)
f021ee
+				return;
f021ee
+
f021ee
 			rc = fsp_queue_msg(rsp, fsp_freemsg);
f021ee
-		if (rc) {
f021ee
-			log_simple_error(&e_info(OPAL_RC_OCC_LOAD),
f021ee
-				"OCC: Error %d queueing FSP OCC LOAD STATUS msg", rc);
f021ee
-			fsp_freemsg(rsp);
f021ee
+			if (rc) {
f021ee
+				log_simple_error(&e_info(OPAL_RC_OCC_LOAD),
f021ee
+				"OCC: Error %d queueing OCC LOAD STATUS msg",
f021ee
+						 rc);
f021ee
+				fsp_freemsg(rsp);
f021ee
+			}
f021ee
+			in_ipl = false;
f021ee
+		} else {
f021ee
+			struct proc_chip *chip = next_chip(NULL);
f021ee
+
f021ee
+			last_seq_id = seq_id;
f021ee
+			prd_fsp_occ_load_start(chip->id);
f021ee
 		}
f021ee
 		return;
f021ee
 	}
f021ee
@@ -1837,8 +1849,6 @@ out:
f021ee
 	return rc;
f021ee
 }
f021ee
 
f021ee
-static u32 last_seq_id;
f021ee
-
f021ee
 int fsp_occ_reset_status(u64 chipid, s64 status)
f021ee
 {
f021ee
 	struct fsp_msg *stat;
f021ee
@@ -1875,6 +1885,38 @@ int fsp_occ_reset_status(u64 chipid, s64
f021ee
 	return rc;
f021ee
 }
f021ee
 
f021ee
+int fsp_occ_load_start_status(u64 chipid, s64 status)
f021ee
+{
f021ee
+	struct fsp_msg *stat;
f021ee
+	int rc = OPAL_NO_MEM;
f021ee
+	int status_word = 0;
f021ee
+
f021ee
+	if (status) {
f021ee
+		struct proc_chip *chip = get_chip(chipid);
f021ee
+
f021ee
+		if (!chip)
f021ee
+			return OPAL_PARAMETER;
f021ee
+
f021ee
+		status_word = 0xB500 | (chip->pcid & 0xff);
f021ee
+		log_simple_error(&e_info(OPAL_RC_OCC_LOAD),
f021ee
+				 "OCC: Error %d in load/start OCC %lld\n", rc,
f021ee
+				 chipid);
f021ee
+	}
f021ee
+
f021ee
+	stat = fsp_mkmsg(FSP_CMD_LOAD_OCC_STAT, 2, status_word, last_seq_id);
f021ee
+	if (!stat)
f021ee
+		return rc;
f021ee
+
f021ee
+	rc = fsp_queue_msg(stat, fsp_freemsg);
f021ee
+	if (rc) {
f021ee
+		fsp_freemsg(stat);
f021ee
+		log_simple_error(&e_info(OPAL_RC_OCC_LOAD),
f021ee
+			"OCC: Error %d queueing FSP OCC LOAD STATUS msg", rc);
f021ee
+	}
f021ee
+
f021ee
+	return rc;
f021ee
+}
f021ee
+
f021ee
 static void occ_do_reset(u8 scope, u32 dbob_id, u32 seq_id)
f021ee
 {
f021ee
 	struct fsp_msg *rsp, *stat;
f021ee
diff -up skiboot-5.9/hw/prd.c.me skiboot-5.9/hw/prd.c
f021ee
--- skiboot-5.9/hw/prd.c.me	2018-01-22 11:44:50.356992133 +0100
f021ee
+++ skiboot-5.9/hw/prd.c	2018-01-22 11:44:50.363991868 +0100
f021ee
@@ -30,6 +30,7 @@ enum events {
f021ee
 	EVENT_OCC_RESET	= 1 << 2,
f021ee
 	EVENT_SBE_PASSTHROUGH = 1 << 3,
f021ee
 	EVENT_FSP_OCC_RESET = 1 << 4,
f021ee
+	EVENT_FSP_OCC_LOAD_START = 1 << 5,
f021ee
 };
f021ee
 
f021ee
 static uint8_t events[MAX_CHIPS];
f021ee
@@ -119,6 +120,10 @@ static void prd_msg_consumed(void *data)
f021ee
 		proc = msg->occ_reset.chip;
f021ee
 		event = EVENT_FSP_OCC_RESET;
f021ee
 		break;
f021ee
+	case OPAL_PRD_MSG_TYPE_FSP_OCC_LOAD_START:
f021ee
+		proc = msg->occ_reset.chip;
f021ee
+		event = EVENT_FSP_OCC_LOAD_START;
f021ee
+		break;
f021ee
 	default:
f021ee
 		prlog(PR_ERR, "PRD: invalid msg consumed, type: 0x%x\n",
f021ee
 				msg->hdr.type);
f021ee
@@ -196,6 +201,9 @@ static void send_next_pending_event(void
f021ee
 	} else if (event & EVENT_FSP_OCC_RESET) {
f021ee
 		prd_msg->hdr.type = OPAL_PRD_MSG_TYPE_FSP_OCC_RESET;
f021ee
 		prd_msg->occ_reset.chip = proc;
f021ee
+	} else if (event & EVENT_FSP_OCC_LOAD_START) {
f021ee
+		prd_msg->hdr.type = OPAL_PRD_MSG_TYPE_FSP_OCC_LOAD_START;
f021ee
+		prd_msg->occ_reset.chip = proc;
f021ee
 	}
f021ee
 
f021ee
 	/*
f021ee
@@ -292,6 +300,11 @@ void prd_sbe_passthrough(uint32_t proc)
f021ee
 	prd_event(proc, EVENT_SBE_PASSTHROUGH);
f021ee
 }
f021ee
 
f021ee
+void prd_fsp_occ_load_start(uint32_t proc)
f021ee
+{
f021ee
+	prd_event(proc, EVENT_FSP_OCC_LOAD_START);
f021ee
+}
f021ee
+
f021ee
 /* incoming message handlers */
f021ee
 static int prd_msg_handle_attn_ack(struct opal_prd_msg *msg)
f021ee
 {
f021ee
@@ -439,6 +452,10 @@ static int64_t opal_prd_msg(struct opal_
f021ee
 		rc = hservice_wakeup(msg->spl_wakeup.core,
f021ee
 				     msg->spl_wakeup.mode);
f021ee
 		break;
f021ee
+	case OPAL_PRD_MSG_TYPE_FSP_OCC_LOAD_START_STATUS:
f021ee
+		rc = fsp_occ_load_start_status(msg->fsp_occ_reset_status.chip,
f021ee
+					msg->fsp_occ_reset_status.status);
f021ee
+		break;
f021ee
 	default:
f021ee
 		rc = OPAL_UNSUPPORTED;
f021ee
 	}
f021ee
diff -up skiboot-5.9/include/hostservices.h.me skiboot-5.9/include/hostservices.h
f021ee
--- skiboot-5.9/include/hostservices.h.me	2018-01-22 11:44:50.363991868 +0100
f021ee
+++ skiboot-5.9/include/hostservices.h	2018-01-22 11:45:21.221824912 +0100
f021ee
@@ -40,5 +40,6 @@ int find_master_and_slave_occ(uint64_t *
f021ee
 			      int *nr_masters, int *nr_slaves);
f021ee
 int hservice_wakeup(uint32_t i_core, uint32_t i_mode);
f021ee
 int fsp_occ_reset_status(u64 chipid, s64 status);
f021ee
+int fsp_occ_load_start_status(u64 chipid, s64 status);
f021ee
 
f021ee
 #endif /* __HOSTSERVICES_H */
f021ee
diff -up skiboot-5.9/include/opal-api.h.me skiboot-5.9/include/opal-api.h
f021ee
--- skiboot-5.9/include/opal-api.h.me	2018-01-22 11:44:50.357992095 +0100
f021ee
+++ skiboot-5.9/include/opal-api.h	2018-01-22 11:44:50.363991868 +0100
f021ee
@@ -1057,6 +1057,8 @@ enum opal_prd_msg_type {
f021ee
 	OPAL_PRD_MSG_TYPE_FSP_OCC_RESET, /* HBRT <-- OPAL */
f021ee
 	OPAL_PRD_MSG_TYPE_FSP_OCC_RESET_STATUS, /* HBRT --> OPAL */
f021ee
 	OPAL_PRD_MSG_TYPE_CORE_SPECIAL_WAKEUP, /* HBRT --> OPAL */
f021ee
+	OPAL_PRD_MSG_TYPE_FSP_OCC_LOAD_START, /* HBRT <-- OPAL */
f021ee
+	OPAL_PRD_MSG_TYPE_FSP_OCC_LOAD_START_STATUS, /* HBRT --> OPAL */
f021ee
 };
f021ee
 
f021ee
 struct opal_prd_msg_header {
f021ee
diff -up skiboot-5.9/include/skiboot.h.me skiboot-5.9/include/skiboot.h
f021ee
--- skiboot-5.9/include/skiboot.h.me	2018-01-22 11:44:50.358992057 +0100
f021ee
+++ skiboot-5.9/include/skiboot.h	2018-01-22 11:44:50.364991831 +0100
f021ee
@@ -294,6 +294,7 @@ extern void prd_sbe_passthrough(uint32_t
f021ee
 extern void prd_init(void);
f021ee
 extern void prd_register_reserved_memory(void);
f021ee
 extern void prd_fsp_occ_reset(uint32_t proc);
f021ee
+extern void prd_fsp_occ_load_start(u32 proc);
f021ee
 
f021ee
 /* Flatten device-tree */
f021ee
 extern void *create_dtb(const struct dt_node *root, bool exclusive);