Re: [PATCH 3/5] firmware: ti_sci: Add support for Device control

From: Lokesh Vutla
Date: Sun Aug 21 2016 - 23:58:15 EST




On Saturday 20 August 2016 04:21 AM, Nishanth Menon wrote:
> Texas Instrument's System Control Interface (TI-SCI) Message Protocol
> is used in Texas Instrument's System on Chip (SoC) such as those
> in keystone family K2G SoC to communicate between various compute
> processors with a central system controller entity.
>
> TI-SCI message protocol provides support for management of various
> hardware entitites within the SoC. Add support driver to allow
> communication with system controller entity within the SoC using the
> mailbox client.
>
> We introduce the fundamental device management capability support to
> the driver protocol as part of this change.
>
> [d-gerlach@xxxxxx: Contributed device reset handling]
> Signed-off-by: Dave Gerlach <d-gerlach@xxxxxx>
> Signed-off-by: Nishanth Menon <nm@xxxxxx>
> ---
> drivers/firmware/ti_sci.c | 433 +++++++++++++++++++++++++++++++++
> drivers/firmware/ti_sci.h | 98 ++++++++
> include/linux/soc/ti/ti_sci_protocol.h | 91 +++++++
> 3 files changed, 622 insertions(+)
>
> diff --git a/drivers/firmware/ti_sci.c b/drivers/firmware/ti_sci.c
> index 4580c29dcb52..e0e286e76095 100644
> --- a/drivers/firmware/ti_sci.c
> +++ b/drivers/firmware/ti_sci.c
> @@ -496,6 +496,437 @@ fail:
> }
>
> /**
> + * tis_sci_is_response_ack() - Generic ACK/NACK message checkup
> + * @r: pointer to response buffer
> + *
> + * Return: true if the response was an ACK, else returns false.
> + */
> +static inline bool tis_sci_is_response_ack(void *r)

May be just ti_sci_is_response_ack() to be consistent? or you wanted to
keep it tis_sci* ?

> +{
> + struct ti_sci_msg_hdr *hdr = r;
> +
> + return hdr->flags & TI_SCI_FLAG_RESP_GENERIC_ACK ? true : false;
> +}
> +
> +/**
> + * ti_sci_set_device_state() - Set device state helper
> + * @handle: pointer to TI SCI handle
> + * @id: Device identifier
> + * @flags: flags to setup for the device
> + * @state: State to move the device to
> + *
> + * Return: 0 if all went well, else returns appropriate error value.
> + */
> +static int ti_sci_set_device_state(const struct ti_sci_handle *handle,
> + u32 id, u32 flags, u8 state)
> +{
> + struct ti_sci_info *info;
> + struct ti_sci_msg_req_set_device_state *req;
> + struct ti_sci_msg_hdr *resp;
> + struct ti_sci_xfer *xfer;
> + struct device *dev;
> + int ret = 0;
> +
> + if (IS_ERR(handle))
> + return PTR_ERR(handle);
> + if (!handle)
> + return -EINVAL;
> +
> + info = handle_to_ti_sci_info(handle);
> + dev = info->dev;
> +
> + xfer = ti_sci_get_one_xfer(info, TI_SCI_MSG_SET_DEVICE_STATE,
> + flags | TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
> + sizeof(*req), sizeof(*resp));
> + if (IS_ERR(xfer)) {
> + ret = PTR_ERR(xfer);
> + dev_err(dev, "Message alloc failed(%d)\n", ret);
> + return ret;
> + }
> + req = (struct ti_sci_msg_req_set_device_state *)xfer->xfer_buf;
> + req->id = id;
> + req->state = state;
> +
> + ret = ti_sci_do_xfer(info, xfer);
> + if (ret) {
> + dev_err(dev, "Mbox send fail %d\n", ret);
> + goto fail;
> + }
> +
> + resp = (struct ti_sci_msg_hdr *)xfer->xfer_buf;
> +
> + ret = tis_sci_is_response_ack(resp) ? 0 : -ENODEV;
> +
> +fail:
> + ti_sci_put_one_xfer(&info->minfo, xfer);
> +
> + return ret;
> +}
> +
> +/**
> + * ti_sci_get_device_state() - Get device state helper
> + * @handle: Handle to the device
> + * @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 went fine, else return appropriate error.
> + */
> +static int ti_sci_get_device_state(const struct ti_sci_handle *handle,
> + u32 id, u32 *clcnt, u32 *resets,
> + u8 *p_state, u8 *c_state)
> +{
> + struct ti_sci_info *info;
> + struct ti_sci_msg_req_get_device_state *req;
> + struct ti_sci_msg_resp_get_device_state *resp;
> + struct ti_sci_xfer *xfer;
> + struct device *dev;
> + int ret = 0;
> +
> + if (IS_ERR(handle))
> + return PTR_ERR(handle);
> + if (!handle)
> + return -EINVAL;
> +
> + if (!clcnt && !resets && !p_state && !c_state)
> + return -EINVAL;
> +
> + info = handle_to_ti_sci_info(handle);
> + dev = info->dev;
> +
> + /* Response is expected, so need of any flags */
^^ no*

Thanks and regards,
Lokesh

> + xfer = ti_sci_get_one_xfer(info, TI_SCI_MSG_GET_DEVICE_STATE,
> + 0, sizeof(*req), sizeof(*resp));
> + if (IS_ERR(xfer)) {
> + ret = PTR_ERR(xfer);
> + dev_err(dev, "Message alloc failed(%d)\n", ret);
> + return ret;
> + }
> + req = (struct ti_sci_msg_req_get_device_state *)xfer->xfer_buf;
> + req->id = id;
> +
> + ret = ti_sci_do_xfer(info, xfer);
> + if (ret) {
> + dev_err(dev, "Mbox send fail %d\n", ret);
> + goto fail;
> + }
> +
> + resp = (struct ti_sci_msg_resp_get_device_state *)xfer->xfer_buf;
> + if (!tis_sci_is_response_ack(resp)) {
> + ret = -ENODEV;
> + goto fail;
> + }
> +
> + 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;
> +fail:
> + ti_sci_put_one_xfer(&info->minfo, xfer);
> +
> + return ret;
> +}
> +
> +/**
> + * ti_sci_cmd_get_device() - command to request for device managed by TISCI
> + * @handle: Pointer to TISCI handle as retrieved by *ti_sci_get_handle
> + * @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 went fine, else return appropriate error.
> + */
> +static int ti_sci_cmd_get_device(const struct ti_sci_handle *handle, u32 id)
> +{
> + return ti_sci_set_device_state(handle, id,
> + MSG_FLAG_DEVICE_EXCLUSIVE,
> + MSG_DEVICE_SW_STATE_ON);
> +}
> +
> +/**
> + * ti_sci_cmd_idle_device() - Command to idle a device managed by TISCI
> + * @handle: Pointer to TISCI handle as retrieved by *ti_sci_get_handle
> + * @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 went fine, else return appropriate error.
> + */
> +static int ti_sci_cmd_idle_device(const struct ti_sci_handle *handle, u32 id)
> +{
> + return ti_sci_set_device_state(handle, id,
> + MSG_FLAG_DEVICE_EXCLUSIVE,
> + MSG_DEVICE_SW_STATE_RETENTION);
> +}
> +
> +/**
> + * ti_sci_cmd_put_device() - command to release a device managed by TISCI
> + * @handle: Pointer to TISCI handle as retrieved by *ti_sci_get_handle
> + * @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 went fine, else return appropriate error.
> + */
> +static int ti_sci_cmd_put_device(const struct ti_sci_handle *handle, u32 id)
> +{
> + return ti_sci_set_device_state(handle, id,
> + 0, MSG_DEVICE_SW_STATE_AUTO_OFF);
> +}
> +
> +/**
> + * ti_sci_cmd_dev_is_valid() - Is the device valid
> + * @handle: Pointer to TISCI handle as retrieved by *ti_sci_get_handle
> + * @id: Device Identifier
> + *
> + * Return: 0 if all went fine and the device ID is valid, else return
> + * appropriate error.
> + */
> +static int ti_sci_cmd_dev_is_valid(const struct ti_sci_handle *handle, u32 id)
> +{
> + u8 unused;
> +
> + /* check the device state which will also tell us if the ID is valid */
> + return ti_sci_get_device_state(handle, id, NULL, NULL, NULL, &unused);
> +}
> +
> +/**
> + * ti_sci_cmd_dev_get_clcnt() - Get context loss counter
> + * @handle: Pointer to TISCI handle
> + * @id: Device Identifier
> + * @count: Pointer to Context Loss counter to populate
> + *
> + * Return: 0 if all went fine, else return appropriate error.
> + */
> +static int ti_sci_cmd_dev_get_clcnt(const struct ti_sci_handle *handle, u32 id,
> + u32 *count)
> +{
> + return ti_sci_get_device_state(handle, id, count, NULL, NULL, NULL);
> +}
> +
> +/**
> + * ti_sci_cmd_dev_is_idle() - Check if the device is requested to be idle
> + * @handle: Pointer to TISCI handle
> + * @id: Device Identifier
> + * @r_state: true if requested to be idle
> + *
> + * Return: 0 if all went fine, else return appropriate error.
> + */
> +static int ti_sci_cmd_dev_is_idle(const struct ti_sci_handle *handle, u32 id,
> + bool *r_state)
> +{
> + int ret;
> + u8 state;
> +
> + if (!r_state)
> + return -EINVAL;
> +
> + ret = ti_sci_get_device_state(handle, id, NULL, NULL, &state, NULL);
> + if (ret)
> + return ret;
> +
> + *r_state = (state == MSG_DEVICE_SW_STATE_RETENTION);
> +
> + return 0;
> +}
> +
> +/**
> + * ti_sci_cmd_dev_is_stop() - Check if the device is requested to be stopped
> + * @handle: Pointer to TISCI handle
> + * @id: Device Identifier
> + * @r_state: true if requested to be stopped
> + * @curr_state: true if currently stopped.
> + *
> + * Return: 0 if all went fine, else return appropriate error.
> + */
> +static int ti_sci_cmd_dev_is_stop(const struct ti_sci_handle *handle, u32 id,
> + bool *r_state, bool *curr_state)
> +{
> + int ret;
> + u8 p_state, c_state;
> +
> + if (!r_state && !curr_state)
> + return -EINVAL;
> +
> + ret =
> + ti_sci_get_device_state(handle, 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_cmd_dev_is_on() - Check if the device is requested to be ON
> + * @handle: Pointer to TISCI handle
> + * @id: Device Identifier
> + * @r_state: true if requested to be ON
> + * @curr_state: true if currently ON and active
> + *
> + * Return: 0 if all went fine, else return appropriate error.
> + */
> +static int ti_sci_cmd_dev_is_on(const struct ti_sci_handle *handle, u32 id,
> + bool *r_state, bool *curr_state)
> +{
> + int ret;
> + u8 p_state, c_state;
> +
> + if (!r_state && !curr_state)
> + return -EINVAL;
> +
> + ret =
> + ti_sci_get_device_state(handle, 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_cmd_dev_is_trans() - Check if the device is currently transitioning
> + * @handle: Pointer to TISCI handle
> + * @id: Device Identifier
> + * @curr_state: true if currently transitioning.
> + *
> + * Return: 0 if all went fine, else return appropriate error.
> + */
> +static int ti_sci_cmd_dev_is_trans(const struct ti_sci_handle *handle, u32 id,
> + bool *curr_state)
> +{
> + int ret;
> + u8 state;
> +
> + if (!curr_state)
> + return -EINVAL;
> +
> + ret = ti_sci_get_device_state(handle, id, NULL, NULL, NULL, &state);
> + if (ret)
> + return ret;
> +
> + *curr_state = (state == MSG_DEVICE_HW_STATE_TRANS);
> +
> + return 0;
> +}
> +
> +/**
> + * ti_sci_cmd_set_device_resets() - command to set resets for device managed
> + * by TISCI
> + * @handle: Pointer to TISCI handle as retrieved by *ti_sci_get_handle
> + * @id: Device Identifier
> + * @reset_state: Device specific reset bit field
> + *
> + * Return: 0 if all went fine, else return appropriate error.
> + */
> +static int ti_sci_cmd_set_device_resets(const struct ti_sci_handle *handle,
> + u32 id, u32 reset_state)
> +{
> + struct ti_sci_info *info;
> + struct ti_sci_msg_req_set_device_resets *req;
> + struct ti_sci_msg_hdr *resp;
> + struct ti_sci_xfer *xfer;
> + struct device *dev;
> + int ret = 0;
> +
> + if (IS_ERR(handle))
> + return PTR_ERR(handle);
> + if (!handle)
> + return -EINVAL;
> +
> + info = handle_to_ti_sci_info(handle);
> + dev = info->dev;
> +
> + xfer = ti_sci_get_one_xfer(info, TI_SCI_MSG_SET_DEVICE_RESETS,
> + TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
> + sizeof(*req), sizeof(*resp));
> + if (IS_ERR(xfer)) {
> + ret = PTR_ERR(xfer);
> + dev_err(dev, "Message alloc failed(%d)\n", ret);
> + return ret;
> + }
> + req = (struct ti_sci_msg_req_set_device_resets *)xfer->xfer_buf;
> + req->id = id;
> + req->resets = reset_state;
> +
> + ret = ti_sci_do_xfer(info, xfer);
> + if (ret) {
> + dev_err(dev, "Mbox send fail %d\n", ret);
> + goto fail;
> + }
> +
> + resp = (struct ti_sci_msg_hdr *)xfer->xfer_buf;
> +
> + ret = tis_sci_is_response_ack(resp) ? 0 : -ENODEV;
> +
> +fail:
> + ti_sci_put_one_xfer(&info->minfo, xfer);
> +
> + return ret;
> +}
> +
> +/**
> + * ti_sci_cmd_get_device_resets() - Get reset state for device managed
> + * by TISCI
> + * @handle: Pointer to TISCI handle
> + * @id: Device Identifier
> + * @reset_state: Pointer to reset state to populate
> + *
> + * Return: 0 if all went fine, else return appropriate error.
> + */
> +static int ti_sci_cmd_get_device_resets(const struct ti_sci_handle *handle,
> + u32 id, u32 *reset_state)
> +{
> + return ti_sci_get_device_state(handle, id, NULL, reset_state, NULL,
> + NULL);
> +}
> +
> +/*
> + * ti_sci_setup_ops() - Setup the operations structures
> + * @info: pointer to TISCI pointer
> + */
> +static void ti_sci_setup_ops(struct ti_sci_info *info)
> +{
> + struct ti_sci_ops *ops = &info->handle.ops;
> + struct ti_sci_dev_ops *dops = &ops->dev_ops;
> +
> + dops->get_device = ti_sci_cmd_get_device;
> + dops->idle_device = ti_sci_cmd_idle_device;
> + dops->put_device = ti_sci_cmd_put_device;
> +
> + dops->is_valid = ti_sci_cmd_dev_is_valid;
> + dops->get_context_loss_count = ti_sci_cmd_dev_get_clcnt;
> + dops->is_idle = ti_sci_cmd_dev_is_idle;
> + dops->is_stop = ti_sci_cmd_dev_is_stop;
> + dops->is_on = ti_sci_cmd_dev_is_on;
> + dops->is_transitioning = ti_sci_cmd_dev_is_trans;
> + dops->set_device_resets = ti_sci_cmd_set_device_resets;
> + dops->get_device_resets = ti_sci_cmd_get_device_resets;
> +}
> +
> +/**
> * ti_sci_get_handle() - Get the TI SCI handle for a device
> * @dev: Pointer to device for which we want SCI handle
> *
> @@ -735,6 +1166,8 @@ static int ti_sci_probe(struct platform_device *pdev)
> goto out;
> }
>
> + ti_sci_setup_ops(info);
> +
> dev_info(dev, "ABI: %d.%d (firmware rev 0x%04x '%s')\n",
> info->handle.version.abi_major, info->handle.version.abi_minor,
> info->handle.version.firmware_revision,
> diff --git a/drivers/firmware/ti_sci.h b/drivers/firmware/ti_sci.h
> index e9dc53f26e0e..29ce0532a7ca 100644
> --- a/drivers/firmware/ti_sci.h
> +++ b/drivers/firmware/ti_sci.h
> @@ -47,6 +47,11 @@
> #define TI_SCI_MSG_WAKE_REASON 0x0003
> #define TI_SCI_MSG_GOODBYE 0x0004
>
> +/* Device requests */
> +#define TI_SCI_MSG_SET_DEVICE_STATE 0x0200
> +#define TI_SCI_MSG_GET_DEVICE_STATE 0x0201
> +#define TI_SCI_MSG_SET_DEVICE_RESETS 0x0202
> +
> /**
> * struct ti_sci_msg_hdr - Generic Message Header for All messages and responses
> * @type: Type of messages: One of TI_SCI_MSG* values
> @@ -90,4 +95,97 @@ struct ti_sci_msg_resp_version {
> u8 abi_minor;
> } __packed;
>
> +/**
> + * struct ti_sci_msg_req_set_device_state - Set the desired state of the device
> + * @hdr: Generic header
> + * @id: Indicates which device to modify
> + * @reserved: Reserved space in message, must be 0 for backward compatibility
> + * @state: The desired state of the device.
> + *
> + * Certain flags can also be set to alter the device state:
> + * + MSG_FLAG_DEVICE_WAKE_ENABLED - Configure the device to be a wake source.
> + * The meaning of this flag will vary slightly from device to device and from
> + * SoC to SoC but it generally allows the device to wake the SoC out of deep
> + * suspend states.
> + * + MSG_FLAG_DEVICE_RESET_ISO - Enable reset isolation for this device.
> + * + MSG_FLAG_DEVICE_EXCLUSIVE - Claim this device exclusively. When passed
> + * with STATE_RETENTION or STATE_ON, it will claim the device exclusively.
> + * If another host already has this device set to STATE_RETENTION or STATE_ON,
> + * the message will fail. Once successful, other hosts attempting to set
> + * STATE_RETENTION or STATE_ON will fail.
> + *
> + * Request type is TI_SCI_MSG_SET_DEVICE_STATE, responded with a generic
> + * ACK/NACK message.
> + */
> +struct ti_sci_msg_req_set_device_state {
> + /* Additional hdr->flags options */
> +#define MSG_FLAG_DEVICE_WAKE_ENABLED TI_SCI_MSG_FLAG(8)
> +#define MSG_FLAG_DEVICE_RESET_ISO TI_SCI_MSG_FLAG(9)
> +#define MSG_FLAG_DEVICE_EXCLUSIVE TI_SCI_MSG_FLAG(10)
> + struct ti_sci_msg_hdr hdr;
> + u32 id;
> + u32 reserved;
> +
> +#define MSG_DEVICE_SW_STATE_AUTO_OFF 0
> +#define MSG_DEVICE_SW_STATE_RETENTION 1
> +#define MSG_DEVICE_SW_STATE_ON 2
> + u8 state;
> +} __packed;
> +
> +/**
> + * struct ti_sci_msg_req_get_device_state - Request to get device.
> + * @hdr: Generic header
> + * @id: Device Identifier
> + *
> + * Request type is TI_SCI_MSG_GET_DEVICE_STATE, responded device state
> + * information
> + */
> +struct ti_sci_msg_req_get_device_state {
> + struct ti_sci_msg_hdr hdr;
> + u32 id;
> +} __packed;
> +
> +/**
> + * struct ti_sci_msg_resp_get_device_state - Response to get device request.
> + * @hdr: Generic header
> + * @context_loss_count: Indicates how many times the device has lost context. A
> + * driver can use this monotonic counter to determine if the device has
> + * lost context since the last time this message was exchanged.
> + * @resets: Programmed state of the reset lines.
> + * @programmed_state: The state as programmed by set_device.
> + * - Uses the MSG_DEVICE_SW_* macros
> + * @current_state: The actual state of the hardware.
> + *
> + * Response to request TI_SCI_MSG_GET_DEVICE_STATE.
> + */
> +struct ti_sci_msg_resp_get_device_state {
> + struct ti_sci_msg_hdr hdr;
> + u32 context_loss_count;
> + u32 resets;
> + u8 programmed_state;
> +#define MSG_DEVICE_HW_STATE_OFF 0
> +#define MSG_DEVICE_HW_STATE_ON 1
> +#define MSG_DEVICE_HW_STATE_TRANS 2
> + u8 current_state;
> +} __packed;
> +
> +/**
> + * struct ti_sci_msg_req_set_device_resets - Set the desired resets
> + * configuration of the device
> + * @hdr: Generic header
> + * @id: Indicates which device to modify
> + * @resets: A bit field of resets for the device. The meaning, behavior,
> + * and usage of the reset flags are device specific. 0 for a bit
> + * indicates releasing the reset represented by that bit while 1
> + * indicates keeping it held.
> + *
> + * Request type is TI_SCI_MSG_SET_DEVICE_RESETS, responded with a generic
> + * ACK/NACK message.
> + */
> +struct ti_sci_msg_req_set_device_resets {
> + struct ti_sci_msg_hdr hdr;
> + u32 id;
> + u32 resets;
> +} __packed;
> +
> #endif /* __TI_SCI_H */
> diff --git a/include/linux/soc/ti/ti_sci_protocol.h b/include/linux/soc/ti/ti_sci_protocol.h
> index e73483fd5327..87fa73851471 100644
> --- a/include/linux/soc/ti/ti_sci_protocol.h
> +++ b/include/linux/soc/ti/ti_sci_protocol.h
> @@ -33,12 +33,103 @@ struct ti_sci_version_info {
> char firmware_description[32];
> };
>
> +struct ti_sci_handle;
> +
> +/**
> + * struct ti_sci_dev_ops - Device control operations
> + * @get_device: Command to request for device managed by TISCI
> + * Returns 0 for successful exclusive request, else returns
> + * corresponding error message.
> + * @idle_device: Command to idle a device managed by TISCI
> + * Returns 0 for successful exclusive request, else returns
> + * corresponding error message.
> + * @put_device: Command to release a device managed by TISCI
> + * Returns 0 for successful release, else returns corresponding
> + * error message.
> + * @is_valid: Check if the device ID is a valid ID.
> + * Returns 0 if the ID is valid, else returns corresponding error.
> + * @get_context_loss_count: Command to retrieve context loss counter - this
> + * increments every time the device looses context. Overflow
> + * is possible.
> + * - count: pointer to u32 which will retrieve counter
> + * Returns 0 for successful information request and count has
> + * proper data, else returns corresponding error message.
> + * @is_idle: Reports back about device idle state
> + * - req_state: Returns requested idle state
> + * Returns 0 for successful information request and req_state and
> + * current_state has proper data, else returns corresponding error
> + * message.
> + * @is_stop: Reports back about device stop state
> + * - req_state: Returns requested stop state
> + * - current_state: Returns current stop state
> + * Returns 0 for successful information request and req_state and
> + * current_state has proper data, else returns corresponding error
> + * message.
> + * @is_on: Reports back about device ON(or active) state
> + * - req_state: Returns requested ON state
> + * - current_state: Returns current ON state
> + * Returns 0 for successful information request and req_state and
> + * current_state has proper data, else returns corresponding error
> + * message.
> + * @is_transitioning: Reports back if the device is in the middle of transition
> + * of state.
> + * -current_state: Returns 'true' if currently transitioning.
> + * @set_device_resets: Command to configure resets for device managed by TISCI.
> + * -reset_state: Device specific reset bit field
> + * Returns 0 for successful request, else returns
> + * corresponding error message.
> + * @get_device_resets: Command to read state of resets for device managed
> + * by TISCI.
> + * -reset_state: pointer to u32 which will retrieve resets
> + * Returns 0 for successful request, else returns
> + * corresponding error message.
> + *
> + * NOTE: for all these functions, the following parameters are generic in
> + * nature:
> + * -handle: Pointer to TISCI handle as retrieved by *ti_sci_get_handle
> + * -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.
> + */
> +struct ti_sci_dev_ops {
> + int (*get_device)(const struct ti_sci_handle *handle, u32 id);
> + int (*idle_device)(const struct ti_sci_handle *handle, u32 id);
> + int (*put_device)(const struct ti_sci_handle *handle, u32 id);
> + int (*is_valid)(const struct ti_sci_handle *handle, u32 id);
> + int (*get_context_loss_count)(const struct ti_sci_handle *handle,
> + u32 id, u32 *count);
> + int (*is_idle)(const struct ti_sci_handle *handle, u32 id,
> + bool *requested_state);
> + int (*is_stop)(const struct ti_sci_handle *handle, u32 id,
> + bool *req_state, bool *current_state);
> + int (*is_on)(const struct ti_sci_handle *handle, u32 id,
> + bool *req_state, bool *current_state);
> + int (*is_transitioning)(const struct ti_sci_handle *handle, u32 id,
> + bool *current_state);
> + int (*set_device_resets)(const struct ti_sci_handle *handle, u32 id,
> + u32 reset_state);
> + int (*get_device_resets)(const struct ti_sci_handle *handle, u32 id,
> + u32 *reset_state);
> +};
> +
> +/**
> + * struct ti_sci_ops - Function support for TI SCI
> + * @dev_ops: Device specific operations
> + */
> +struct ti_sci_ops {
> + struct ti_sci_dev_ops dev_ops;
> +};
> +
> /**
> * struct ti_sci_handle - Handle returned to TI SCI clients for usage.
> * @version: structure containing version information
> + * @ops: operations that are made available to TI SCI clients
> */
> struct ti_sci_handle {
> struct ti_sci_version_info version;
> + struct ti_sci_ops ops;
> };
>
> #if IS_ENABLED(CONFIG_TI_SCI_PROTOCOL)
>