summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--plat/ti/k3/common/drivers/ti_sci/ti_sci.c357
-rw-r--r--plat/ti/k3/common/drivers/ti_sci/ti_sci.h59
2 files changed, 416 insertions, 0 deletions
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 47dc777f..be77dc82 100644
--- a/plat/ti/k3/common/drivers/ti_sci/ti_sci.c
+++ b/plat/ti/k3/common/drivers/ti_sci/ti_sci.c
@@ -205,6 +205,363 @@ int ti_sci_get_revision(struct ti_sci_msg_resp_version *rev_info)
}
/**
+ * ti_sci_is_response_ack() - Generic ACK/NACK message check
+ *
+ * @r: pointer to response buffer
+ *
+ * Return: true if the response was an ACK, else returns false
+ */
+static inline bool ti_sci_is_response_ack(void *r)
+{
+ struct ti_sci_msg_hdr *hdr = r;
+
+ return hdr->flags & TI_SCI_FLAG_RESP_GENERIC_ACK ? true : false;
+}
+
+/**
+ * ti_sci_device_set_state() - Set device state
+ *
+ * @id: Device identifier
+ * @flags: flags to setup for the device
+ * @state: State to move the device to
+ *
+ * Return: 0 if all goes well, else appropriate error message
+ */
+int ti_sci_device_set_state(uint32_t id, uint32_t flags, uint8_t state)
+{
+ struct ti_sci_msg_req_set_device_state req;
+ struct ti_sci_msg_hdr resp;
+
+ struct ti_sci_xfer xfer;
+ int ret;
+
+ ret = ti_sci_setup_one_xfer(TI_SCI_MSG_SET_DEVICE_STATE,
+ flags | 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.id = id;
+ req.state = state;
+
+ 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_device_get_state() - Get device state
+ *
+ * @id: Device Identifier
+ * @clcnt: Pointer to Context Loss Count
+ * @resets: pointer to resets
+ * @p_state: pointer to p_state
+ * @c_state: pointer to c_state
+ *
+ * Return: 0 if all goes well, else appropriate error message
+ */
+int ti_sci_device_get_state(uint32_t id, uint32_t *clcnt, uint32_t *resets,
+ uint8_t *p_state, uint8_t *c_state)
+{
+ struct ti_sci_msg_req_get_device_state req;
+ struct ti_sci_msg_resp_get_device_state resp;
+
+ struct ti_sci_xfer xfer;
+ int ret;
+
+ if (!clcnt && !resets && !p_state && !c_state)
+ return -EINVAL;
+
+ ret = ti_sci_setup_one_xfer(TI_SCI_MSG_GET_DEVICE_STATE, 0,
+ &req, sizeof(req),
+ &resp, sizeof(resp),
+ &xfer);
+ if (ret) {
+ ERROR("Message alloc failed (%d)\n", ret);
+ return ret;
+ }
+
+ req.id = 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;
+
+ if (clcnt)
+ *clcnt = resp.context_loss_count;
+ if (resets)
+ *resets = resp.resets;
+ if (p_state)
+ *p_state = resp.programmed_state;
+ if (c_state)
+ *c_state = resp.current_state;
+
+ return 0;
+}
+
+/**
+ * ti_sci_device_get() - Request for device managed by TISCI
+ *
+ * @id: Device Identifier
+ *
+ * Request for the device - NOTE: the client MUST maintain integrity of
+ * usage count by balancing get_device with put_device. No refcounting is
+ * managed by driver for that purpose.
+ *
+ * NOTE: The request is for exclusive access for the processor.
+ *
+ * Return: 0 if all goes well, else appropriate error message
+ */
+int ti_sci_device_get(uint32_t id)
+{
+ return ti_sci_device_set_state(id,
+ MSG_FLAG_DEVICE_EXCLUSIVE,
+ MSG_DEVICE_SW_STATE_ON);
+}
+
+/**
+ * ti_sci_device_idle() - Idle a device managed by TISCI
+ *
+ * @id: Device Identifier
+ *
+ * Request for the device - NOTE: the client MUST maintain integrity of
+ * usage count by balancing get_device with put_device. No refcounting is
+ * managed by driver for that purpose.
+ *
+ * Return: 0 if all goes well, else appropriate error message
+ */
+int ti_sci_device_idle(uint32_t id)
+{
+ return ti_sci_device_set_state(id,
+ MSG_FLAG_DEVICE_EXCLUSIVE,
+ MSG_DEVICE_SW_STATE_RETENTION);
+}
+
+/**
+ * ti_sci_device_put() - Release a device managed by TISCI
+ *
+ * @id: Device Identifier
+ *
+ * Request for the device - NOTE: the client MUST maintain integrity of
+ * usage count by balancing get_device with put_device. No refcounting is
+ * managed by driver for that purpose.
+ *
+ * Return: 0 if all goes well, else appropriate error message
+ */
+int ti_sci_device_put(uint32_t id)
+{
+ return ti_sci_device_set_state(id, 0, MSG_DEVICE_SW_STATE_AUTO_OFF);
+}
+
+/**
+ * ti_sci_device_is_valid() - Is the device valid
+ *
+ * @id: Device Identifier
+ *
+ * Return: 0 if all goes well and the device ID is valid, else return
+ * appropriate error
+ */
+int ti_sci_device_is_valid(uint32_t id)
+{
+ uint8_t unused;
+
+ /* check the device state which will also tell us if the ID is valid */
+ return ti_sci_device_get_state(id, NULL, NULL, NULL, &unused);
+}
+
+/**
+ * ti_sci_device_get_clcnt() - Get context loss counter
+ *
+ * @id: Device Identifier
+ * @count: Pointer to Context Loss counter to populate
+ *
+ * Return: 0 if all goes well, else appropriate error message
+ */
+int ti_sci_device_get_clcnt(uint32_t id, uint32_t *count)
+{
+ return ti_sci_device_get_state(id, count, NULL, NULL, NULL);
+}
+
+/**
+ * ti_sci_device_is_idle() - Check if the device is requested to be idle
+ *
+ * @id: Device Identifier
+ * @r_state: true if requested to be idle
+ *
+ * Return: 0 if all goes well, else appropriate error message
+ */
+int ti_sci_device_is_idle(uint32_t id, bool *r_state)
+{
+ int ret;
+ uint8_t state;
+
+ if (!r_state)
+ return -EINVAL;
+
+ ret = ti_sci_device_get_state(id, NULL, NULL, &state, NULL);
+ if (ret)
+ return ret;
+
+ *r_state = (state == MSG_DEVICE_SW_STATE_RETENTION);
+
+ return 0;
+}
+
+/**
+ * ti_sci_device_is_stop() - Check if the device is requested to be stopped
+ *
+ * @id: Device Identifier
+ * @r_state: true if requested to be stopped
+ * @curr_state: true if currently stopped
+ *
+ * Return: 0 if all goes well, else appropriate error message
+ */
+int ti_sci_device_is_stop(uint32_t id, bool *r_state, bool *curr_state)
+{
+ int ret;
+ uint8_t p_state, c_state;
+
+ if (!r_state && !curr_state)
+ return -EINVAL;
+
+ ret = ti_sci_device_get_state(id, NULL, NULL, &p_state, &c_state);
+ if (ret)
+ return ret;
+
+ if (r_state)
+ *r_state = (p_state == MSG_DEVICE_SW_STATE_AUTO_OFF);
+ if (curr_state)
+ *curr_state = (c_state == MSG_DEVICE_HW_STATE_OFF);
+
+ return 0;
+}
+
+/**
+ * ti_sci_device_is_on() - Check if the device is requested to be ON
+ *
+ * @id: Device Identifier
+ * @r_state: true if requested to be ON
+ * @curr_state: true if currently ON and active
+ *
+ * Return: 0 if all goes well, else appropriate error message
+ */
+int ti_sci_device_is_on(uint32_t id, bool *r_state, bool *curr_state)
+{
+ int ret;
+ uint8_t p_state, c_state;
+
+ if (!r_state && !curr_state)
+ return -EINVAL;
+
+ ret =
+ ti_sci_device_get_state(id, NULL, NULL, &p_state, &c_state);
+ if (ret)
+ return ret;
+
+ if (r_state)
+ *r_state = (p_state == MSG_DEVICE_SW_STATE_ON);
+ if (curr_state)
+ *curr_state = (c_state == MSG_DEVICE_HW_STATE_ON);
+
+ return 0;
+}
+
+/**
+ * ti_sci_device_is_trans() - Check if the device is currently transitioning
+ *
+ * @id: Device Identifier
+ * @curr_state: true if currently transitioning
+ *
+ * Return: 0 if all goes well, else appropriate error message
+ */
+int ti_sci_device_is_trans(uint32_t id, bool *curr_state)
+{
+ int ret;
+ uint8_t state;
+
+ if (!curr_state)
+ return -EINVAL;
+
+ ret = ti_sci_device_get_state(id, NULL, NULL, NULL, &state);
+ if (ret)
+ return ret;
+
+ *curr_state = (state == MSG_DEVICE_HW_STATE_TRANS);
+
+ return 0;
+}
+
+/**
+ * ti_sci_device_set_resets() - Set resets for device managed by TISCI
+ *
+ * @id: Device Identifier
+ * @reset_state: Device specific reset bit field
+ *
+ * Return: 0 if all goes well, else appropriate error message
+ */
+int ti_sci_device_set_resets(uint32_t id, uint32_t reset_state)
+{
+ struct ti_sci_msg_req_set_device_resets req;
+ struct ti_sci_msg_hdr resp;
+
+ struct ti_sci_xfer xfer;
+ int ret;
+
+ ret = ti_sci_setup_one_xfer(TI_SCI_MSG_SET_DEVICE_RESETS,
+ 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.id = id;
+ req.resets = reset_state;
+
+ 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_device_get_resets() - Get reset state for device managed by TISCI
+ *
+ * @id: Device Identifier
+ * @reset_state: Pointer to reset state to populate
+ *
+ * Return: 0 if all goes well, else appropriate error message
+ */
+int ti_sci_device_get_resets(uint32_t id, uint32_t *reset_state)
+{
+ return ti_sci_device_get_state(id, NULL, reset_state, NULL, NULL);
+}
+
+/**
* 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 f8b65050..3056bda7 100644
--- a/plat/ti/k3/common/drivers/ti_sci/ti_sci.h
+++ b/plat/ti/k3/common/drivers/ti_sci/ti_sci.h
@@ -10,6 +10,65 @@
#ifndef __TI_SCI_H
#define __TI_SCI_H
+#include <stdint.h>
+#include <stdbool.h>
+
+/**
+ * Device control operations
+ *
+ * - ti_sci_device_set_state - Set device state helper
+ * @flags: flags to setup for the device
+ * @state: State to move the device to
+ * - ti_sci_device_get_state - Get device state helper
+ * @clcnt: Pointer to Context Loss Count
+ * @resets: pointer to resets
+ * @p_state: pointer to p_state
+ * @c_state: pointer to c_state
+ * - ti_sci_device_get - command to request for device managed by TISCI
+ * - ti_sci_device_idle - Command to idle a device managed by TISCI
+ * - ti_sci_device_put - command to release a device managed by TISCI
+ * - ti_sci_device_is_valid - Is the device valid
+ * - ti_sci_device_get_clcnt - Get context loss counter
+ * @count: Pointer to Context Loss counter to populate
+ * - ti_sci_device_is_idle - Check if the device is requested to be idle
+ * @r_state: true if requested to be idle
+ * - ti_sci_device_is_stop - Check if the device is requested to be stopped
+ * @r_state: true if requested to be stopped
+ * @curr_state: true if currently stopped.
+ * - ti_sci_device_is_on - Check if the device is requested to be ON
+ * @r_state: true if requested to be ON
+ * @curr_state: true if currently ON and active
+ * - ti_sci_device_is_trans - Check if the device is currently transitioning
+ * @curr_state: true if currently transitioning.
+ * - ti_sci_device_set_resets - Command to set resets for
+ * device managed by TISCI
+ * @reset_state: Device specific reset bit field
+ * - ti_sci_device_get_resets - Get reset state for device managed by TISCI
+ * @reset_state: Pointer to reset state to populate
+ *
+ * NOTE: for all these functions, the following are generic in nature:
+ * @id: Device Identifier
+ * Returns 0 for successful request, else returns corresponding error message.
+ *
+ * Request for the device - NOTE: the client MUST maintain integrity of
+ * usage count by balancing get_device with put_device. No refcounting is
+ * managed by driver for that purpose.
+ */
+int ti_sci_device_set_state(uint32_t id, uint32_t flags, uint8_t state);
+int ti_sci_device_get_state(uint32_t id, uint32_t *clcnt, uint32_t *resets,
+ uint8_t *p_state, uint8_t *c_state);
+int ti_sci_device_get(uint32_t id);
+int ti_sci_device_idle(uint32_t id);
+int ti_sci_device_put(uint32_t id);
+int ti_sci_device_is_valid(uint32_t id);
+int ti_sci_device_get_clcnt(uint32_t id, uint32_t *count);
+int ti_sci_device_is_idle(uint32_t id, bool *r_state);
+int ti_sci_device_is_stop(uint32_t id, bool *r_state, bool *curr_state);
+int ti_sci_device_is_on(uint32_t id, bool *r_state, bool *curr_state);
+int ti_sci_device_is_trans(uint32_t id, bool *curr_state);
+int ti_sci_device_set_resets(uint32_t id, uint32_t reset_state);
+int ti_sci_device_get_resets(uint32_t id, uint32_t *reset_state);
+
/**
* ti_sci_init() - Basic initialization
*