diff options
-rw-r--r-- | plat/ti/k3/common/drivers/ti_sci/ti_sci.c | 357 | ||||
-rw-r--r-- | plat/ti/k3/common/drivers/ti_sci/ti_sci.h | 59 |
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 * |