ti: k3: drivers: ti_sci: Add support for Processor control

TI-SCI message protocol provides support for controlling of various
physical cores available in the SoC. In order to control which host is
capable of controlling a physical processor core, there is a processor
access control list that needs to be populated as part of the board
configuration data.

Introduce support for the set of TI-SCI message protocol APIs that
provide us with this capability of controlling physical cores.

Signed-off-by: Andrew F. Davis <afd@ti.com>
Reviewed-by: Andreas Dannenberg <dannenberg@ti.com>
diff --git a/plat/ti/k3/common/drivers/ti_sci/ti_sci.c b/plat/ti/k3/common/drivers/ti_sci/ti_sci.c
index f5d2ce1..7ba0267 100644
--- a/plat/ti/k3/common/drivers/ti_sci/ti_sci.c
+++ b/plat/ti/k3/common/drivers/ti_sci/ti_sci.c
@@ -1153,6 +1153,311 @@
 }
 
 /**
+ * ti_sci_proc_request() - Request a physical processor control
+ *
+ * @proc_id:	Processor ID this request is for
+ *
+ * Return: 0 if all goes well, else appropriate error message
+ */
+int ti_sci_proc_request(uint8_t proc_id)
+{
+	struct ti_sci_msg_req_proc_request req;
+	struct ti_sci_msg_hdr resp;
+
+	struct ti_sci_xfer xfer;
+	int ret;
+
+	ret = ti_sci_setup_one_xfer(TISCI_MSG_PROC_REQUEST,
+				    TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
+				    &req, sizeof(req),
+				    &resp, sizeof(resp),
+				    &xfer);
+	if (ret) {
+		ERROR("Message alloc failed (%d)\n", ret);
+		return ret;
+	}
+
+	req.processor_id = proc_id;
+
+	ret = ti_sci_do_xfer(&xfer);
+	if (ret) {
+		ERROR("Transfer send failed (%d)\n", ret);
+		return ret;
+	}
+
+	if (!ti_sci_is_response_ack(&resp))
+		return -ENODEV;
+
+	return 0;
+}
+
+/**
+ * ti_sci_proc_release() - Release a physical processor control
+ *
+ * @proc_id:	Processor ID this request is for
+ *
+ * Return: 0 if all goes well, else appropriate error message
+ */
+int ti_sci_proc_release(uint8_t proc_id)
+{
+	struct ti_sci_msg_req_proc_release req;
+	struct ti_sci_msg_hdr resp;
+
+	struct ti_sci_xfer xfer;
+	int ret;
+
+	ret = ti_sci_setup_one_xfer(TISCI_MSG_PROC_RELEASE,
+				    TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
+				    &req, sizeof(req),
+				    &resp, sizeof(resp),
+				    &xfer);
+	if (ret) {
+		ERROR("Message alloc failed (%d)\n", ret);
+		return ret;
+	}
+
+	req.processor_id = proc_id;
+
+	ret = ti_sci_do_xfer(&xfer);
+	if (ret) {
+		ERROR("Transfer send failed (%d)\n", ret);
+		return ret;
+	}
+
+	if (!ti_sci_is_response_ack(&resp))
+		return -ENODEV;
+
+	return 0;
+}
+
+/**
+ * ti_sci_proc_handover() - Handover a physical processor control to a host in
+ *                          the processor's access control list.
+ *
+ * @proc_id:	Processor ID this request is for
+ * @host_id:	Host ID to get the control of the processor
+ *
+ * Return: 0 if all goes well, else appropriate error message
+ */
+int ti_sci_proc_handover(uint8_t proc_id, uint8_t host_id)
+{
+	struct ti_sci_msg_req_proc_handover req;
+	struct ti_sci_msg_hdr resp;
+
+	struct ti_sci_xfer xfer;
+	int ret;
+
+	ret = ti_sci_setup_one_xfer(TISCI_MSG_PROC_HANDOVER,
+				    TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
+				    &req, sizeof(req),
+				    &resp, sizeof(resp),
+				    &xfer);
+	if (ret) {
+		ERROR("Message alloc failed (%d)\n", ret);
+		return ret;
+	}
+
+	req.processor_id = proc_id;
+	req.host_id = host_id;
+
+	ret = ti_sci_do_xfer(&xfer);
+	if (ret) {
+		ERROR("Transfer send failed (%d)\n", ret);
+		return ret;
+	}
+
+	if (!ti_sci_is_response_ack(&resp))
+		return -ENODEV;
+
+	return 0;
+}
+
+/**
+ * ti_sci_proc_set_boot_cfg() - Set the processor boot configuration flags
+ *
+ * @proc_id:		Processor ID this request is for
+ * @config_flags_set:	Configuration flags to be set
+ * @config_flags_clear:	Configuration flags to be cleared
+ *
+ * Return: 0 if all goes well, else appropriate error message
+ */
+int ti_sci_proc_set_boot_cfg(uint8_t proc_id, uint64_t bootvector,
+			     uint32_t config_flags_set,
+			     uint32_t config_flags_clear)
+{
+	struct ti_sci_msg_req_set_proc_boot_config req;
+	struct ti_sci_msg_hdr resp;
+
+	struct ti_sci_xfer xfer;
+	int ret;
+
+	ret = ti_sci_setup_one_xfer(TISCI_MSG_SET_PROC_BOOT_CONFIG,
+				    TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
+				    &req, sizeof(req),
+				    &resp, sizeof(resp),
+				    &xfer);
+	if (ret) {
+		ERROR("Message alloc failed (%d)\n", ret);
+		return ret;
+	}
+
+	req.processor_id = proc_id;
+	req.bootvector_low = bootvector & TISCI_ADDR_LOW_MASK;
+	req.bootvector_high = (bootvector & TISCI_ADDR_HIGH_MASK) >>
+				TISCI_ADDR_HIGH_SHIFT;
+	req.config_flags_set = config_flags_set;
+	req.config_flags_clear = config_flags_clear;
+
+	ret = ti_sci_do_xfer(&xfer);
+	if (ret) {
+		ERROR("Transfer send failed (%d)\n", ret);
+		return ret;
+	}
+
+	if (!ti_sci_is_response_ack(&resp))
+		return -ENODEV;
+
+	return 0;
+}
+
+/**
+ * ti_sci_proc_set_boot_ctrl() - Set the processor boot control flags
+ *
+ * @proc_id:			Processor ID this request is for
+ * @control_flags_set:		Control flags to be set
+ * @control_flags_clear:	Control flags to be cleared
+ *
+ * Return: 0 if all goes well, else appropriate error message
+ */
+int ti_sci_proc_set_boot_ctrl(uint8_t proc_id, uint32_t control_flags_set,
+			      uint32_t control_flags_clear)
+{
+	struct ti_sci_msg_req_set_proc_boot_ctrl req;
+	struct ti_sci_msg_hdr resp;
+
+	struct ti_sci_xfer xfer;
+	int ret;
+
+	ret = ti_sci_setup_one_xfer(TISCI_MSG_SET_PROC_BOOT_CTRL,
+				    TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
+				    &req, sizeof(req),
+				    &resp, sizeof(resp),
+				    &xfer);
+	if (ret) {
+		ERROR("Message alloc failed (%d)\n", ret);
+		return ret;
+	}
+
+	req.processor_id = proc_id;
+	req.control_flags_set = control_flags_set;
+	req.control_flags_clear = control_flags_clear;
+
+	ret = ti_sci_do_xfer(&xfer);
+	if (ret) {
+		ERROR("Transfer send failed (%d)\n", ret);
+		return ret;
+	}
+
+	if (!ti_sci_is_response_ack(&resp))
+		return -ENODEV;
+
+	return 0;
+}
+
+/**
+ * ti_sci_proc_auth_boot_image() - Authenticate and load image and then set the
+ *                                 processor configuration flags
+ *
+ * @proc_id:	Processor ID this request is for
+ * @cert_addr:	Memory address at which payload image certificate is located
+ *
+ * Return: 0 if all goes well, else appropriate error message
+ */
+int ti_sci_proc_auth_boot_image(uint8_t proc_id, uint64_t cert_addr)
+{
+	struct ti_sci_msg_req_proc_auth_boot_image req;
+	struct ti_sci_msg_hdr resp;
+
+	struct ti_sci_xfer xfer;
+	int ret;
+
+	ret = ti_sci_setup_one_xfer(TISCI_MSG_PROC_AUTH_BOOT_IMIAGE,
+				    TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
+				    &req, sizeof(req),
+				    &resp, sizeof(resp),
+				    &xfer);
+	if (ret) {
+		ERROR("Message alloc failed (%d)\n", ret);
+		return ret;
+	}
+
+	req.processor_id = proc_id;
+	req.cert_addr_low = cert_addr & TISCI_ADDR_LOW_MASK;
+	req.cert_addr_high = (cert_addr & TISCI_ADDR_HIGH_MASK) >>
+				TISCI_ADDR_HIGH_SHIFT;
+
+	ret = ti_sci_do_xfer(&xfer);
+	if (ret) {
+		ERROR("Transfer send failed (%d)\n", ret);
+		return ret;
+	}
+
+	if (!ti_sci_is_response_ack(&resp))
+		return -ENODEV;
+
+	return 0;
+}
+
+/**
+ * ti_sci_proc_get_boot_status() - Get the processor boot status
+ *
+ * @proc_id:	Processor ID this request is for
+ *
+ * Return: 0 if all goes well, else appropriate error message
+ */
+int ti_sci_proc_get_boot_status(uint8_t proc_id, uint64_t *bv,
+				uint32_t *cfg_flags,
+				uint32_t *ctrl_flags,
+				uint32_t *sts_flags)
+{
+	struct ti_sci_msg_req_get_proc_boot_status req;
+	struct ti_sci_msg_resp_get_proc_boot_status resp;
+
+	struct ti_sci_xfer xfer;
+	int ret;
+
+	ret = ti_sci_setup_one_xfer(TISCI_MSG_GET_PROC_BOOT_STATUS,
+				    TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
+				    &req, sizeof(req),
+				    &resp, sizeof(resp),
+				    &xfer);
+	if (ret) {
+		ERROR("Message alloc failed (%d)\n", ret);
+		return ret;
+	}
+
+	req.processor_id = proc_id;
+
+	ret = ti_sci_do_xfer(&xfer);
+	if (ret) {
+		ERROR("Transfer send failed (%d)\n", ret);
+		return ret;
+	}
+
+	if (!ti_sci_is_response_ack(&resp))
+		return -ENODEV;
+
+	*bv = (resp.bootvector_low & TISCI_ADDR_LOW_MASK) |
+	      (((uint64_t)resp.bootvector_high << TISCI_ADDR_HIGH_SHIFT) &
+	       TISCI_ADDR_HIGH_MASK);
+	*cfg_flags = resp.config_flags;
+	*ctrl_flags = resp.control_flags;
+	*sts_flags = resp.status_flags;
+
+	return 0;
+}
+
+/**
  * ti_sci_init() - Basic initialization
  *
  * Return: 0 if all goes well, else appropriate error message
diff --git a/plat/ti/k3/common/drivers/ti_sci/ti_sci.h b/plat/ti/k3/common/drivers/ti_sci/ti_sci.h
index df0c13e..e40ad6b 100644
--- a/plat/ti/k3/common/drivers/ti_sci/ti_sci.h
+++ b/plat/ti/k3/common/drivers/ti_sci/ti_sci.h
@@ -162,6 +162,43 @@
 int ti_sci_core_reboot(void);
 
 /**
+ * Processor control operations
+ *
+ * - ti_sci_proc_request - Command to request a physical processor control
+ * - ti_sci_proc_release - Command to release a physical processor control
+ * - ti_sci_proc_handover - Command to handover a physical processor control to
+ *                          a host in the processor's access control list.
+ *              @host_id: Host ID to get the control of the processor
+ * - ti_sci_proc_set_boot_cfg - Command to set the processor boot configuration flags
+ *              @config_flags_set: Configuration flags to be set
+ *              @config_flags_clear: Configuration flags to be cleared.
+ * - ti_sci_proc_set_boot_ctrl - Command to set the processor boot control flags
+ *              @control_flags_set: Control flags to be set
+ *              @control_flags_clear: Control flags to be cleared
+ * - ti_sci_proc_auth_boot_image - Command to authenticate and load the image
+ *                                 and then set the processor configuration flags.
+ *              @cert_addr: Memory address at which payload image certificate is located.
+ * - ti_sci_proc_get_boot_status - Command to get the processor boot status
+ *
+ * NOTE: for all these functions, the following are generic in nature:
+ * @proc_id:	Processor ID
+ * Returns 0 for successful request, else returns corresponding error message.
+ */
+int ti_sci_proc_request(uint8_t proc_id);
+int ti_sci_proc_release(uint8_t proc_id);
+int ti_sci_proc_handover(uint8_t proc_id, uint8_t host_id);
+int ti_sci_proc_set_boot_cfg(uint8_t proc_id, uint64_t bootvector,
+			     uint32_t config_flags_set,
+			     uint32_t config_flags_clear);
+int ti_sci_proc_set_boot_ctrl(uint8_t proc_id, uint32_t control_flags_set,
+			      uint32_t control_flags_clear);
+int ti_sci_proc_auth_boot_image(uint8_t proc_id, uint64_t cert_addr);
+int ti_sci_proc_get_boot_status(uint8_t proc_id, uint64_t *bv,
+				uint32_t *cfg_flags,
+				uint32_t *ctrl_flags,
+				uint32_t *sts_flags);
+
+/**
  * ti_sci_init() - Basic initialization
  *
  * Return: 0 if all goes good, else appropriate error message.