soc/qcom: rpmh: add RPMh read
Implement support for RPMh reads, these allow reading out the current votes for RPMh controlled resources such as regulators and interconnects. Link: https://patch.msgid.link/20260108-rpmh-regulator-fixes-v1-4-d1b5b300b665@linaro.org Signed-off-by: Casey Connolly <casey.connolly@linaro.org>
This commit is contained in:
@@ -282,12 +282,15 @@ static void __tcs_buffer_write(struct rsc_drv *drv, int tcs_id, int cmd_id,
|
||||
const struct tcs_request *msg)
|
||||
{
|
||||
u32 msgid;
|
||||
u32 cmd_msgid = CMD_MSGID_LEN | CMD_MSGID_WRITE;
|
||||
u32 cmd_msgid = CMD_MSGID_LEN;
|
||||
u32 cmd_enable = 0;
|
||||
u32 cmd_complete = 0;
|
||||
struct tcs_cmd *cmd;
|
||||
int i, j;
|
||||
|
||||
if (!msg->is_read)
|
||||
cmd_msgid |= CMD_MSGID_WRITE;
|
||||
|
||||
if (msg->wait_for_compl)
|
||||
cmd_msgid |= CMD_MSGID_RESP_REQ;
|
||||
|
||||
@@ -302,7 +305,8 @@ static void __tcs_buffer_write(struct rsc_drv *drv, int tcs_id, int cmd_id,
|
||||
|
||||
write_tcs_cmd(drv, drv->regs[RSC_DRV_CMD_MSGID], tcs_id, j, msgid);
|
||||
write_tcs_cmd(drv, drv->regs[RSC_DRV_CMD_ADDR], tcs_id, j, cmd->addr);
|
||||
write_tcs_cmd(drv, drv->regs[RSC_DRV_CMD_DATA], tcs_id, j, cmd->data);
|
||||
if (!msg->is_read)
|
||||
write_tcs_cmd(drv, drv->regs[RSC_DRV_CMD_DATA], tcs_id, j, cmd->data);
|
||||
debug("tcs(%d): [%s] cmd_id: %d: msgid: %#x addr: %#x data: %#x complete: %#x\n",
|
||||
tcs_id, msg->state == RPMH_ACTIVE_ONLY_STATE ? "active" : "?", j, msgid,
|
||||
cmd->addr, cmd->data, cmd_complete);
|
||||
@@ -418,6 +422,12 @@ int rpmh_rsc_send_data(struct rsc_drv *drv, const struct tcs_request *msg)
|
||||
udelay(1);
|
||||
}
|
||||
|
||||
/* U-Boot: read the response now we know it's available */
|
||||
if (msg->is_read) {
|
||||
msg->cmds[0].data = read_tcs_cmd(drv, drv->regs[RSC_DRV_CMD_RESP_DATA], tcs_id, 0);
|
||||
log_debug("data response: %#x\n", msg->cmds[0].data);
|
||||
}
|
||||
|
||||
__tcs_set_trigger(drv, tcs_id, false);
|
||||
|
||||
/* Reclaim the TCS */
|
||||
|
||||
@@ -68,7 +68,7 @@ static int __rpmh_write(const struct udevice *dev, enum rpmh_state state,
|
||||
}
|
||||
|
||||
static int __fill_rpmh_msg(struct rpmh_request *req, enum rpmh_state state,
|
||||
const struct tcs_cmd *cmd, u32 n)
|
||||
const struct tcs_cmd *cmd, u32 n, bool is_read)
|
||||
{
|
||||
if (!cmd || !n || n > MAX_RPMH_PAYLOAD)
|
||||
return -EINVAL;
|
||||
@@ -78,12 +78,45 @@ static int __fill_rpmh_msg(struct rpmh_request *req, enum rpmh_state state,
|
||||
req->msg.state = state;
|
||||
req->msg.cmds = req->cmd;
|
||||
req->msg.num_cmds = n;
|
||||
req->msg.is_read = is_read;
|
||||
|
||||
debug("rpmh_msg: %d, %d cmds [first %#x/%#x]\n", state, n, cmd->addr, cmd->data);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* rpmh_read: Read a resource value
|
||||
*
|
||||
* @dev: The device making the request
|
||||
* @cmd: The payload having address of resource to read
|
||||
*
|
||||
* Reads the value for the resource address given in tcs_cmd->addr
|
||||
* and returns the tcs_cmd->data filled with same.
|
||||
*
|
||||
* May sleep. Do not call from atomic contexts.
|
||||
*
|
||||
* Return: 0 on success, negative errno on failure
|
||||
*/
|
||||
int rpmh_read(const struct udevice *dev, enum rpmh_state state, struct tcs_cmd *cmd)
|
||||
{
|
||||
DEFINE_RPMH_MSG_ONSTACK(dev, state, rpm_msg);
|
||||
int ret;
|
||||
|
||||
ret = __fill_rpmh_msg(&rpm_msg, state, cmd, 1, true);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = __rpmh_write(dev, state, &rpm_msg);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* Read back the response into the cmd data structure */
|
||||
cmd->data = rpm_msg.cmd[0].data;
|
||||
|
||||
return (ret > 0) ? 0 : ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* rpmh_write: Write a set of RPMH commands and block until response
|
||||
*
|
||||
@@ -100,7 +133,7 @@ int rpmh_write(const struct udevice *dev, enum rpmh_state state,
|
||||
DEFINE_RPMH_MSG_ONSTACK(dev, state, rpm_msg);
|
||||
int ret;
|
||||
|
||||
ret = __fill_rpmh_msg(&rpm_msg, state, cmd, n);
|
||||
ret = __fill_rpmh_msg(&rpm_msg, state, cmd, n, false);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
|
||||
@@ -13,12 +13,14 @@
|
||||
#if IS_ENABLED(CONFIG_QCOM_RPMH)
|
||||
int rpmh_write(const struct udevice *dev, enum rpmh_state state,
|
||||
const struct tcs_cmd *cmd, u32 n);
|
||||
|
||||
int rpmh_read(const struct udevice *dev, enum rpmh_state state, struct tcs_cmd *cmd);
|
||||
#else
|
||||
|
||||
static inline int rpmh_write(const struct device *dev, enum rpmh_state state,
|
||||
const struct tcs_cmd *cmd, u32 n)
|
||||
{ return -ENODEV; }
|
||||
static inline int rpmh_read(const struct udevice *dev, struct tcs_cmd *cmd)
|
||||
{ return -ENODEV; }
|
||||
|
||||
#endif /* CONFIG_QCOM_RPMH */
|
||||
|
||||
|
||||
@@ -55,6 +55,7 @@ struct tcs_cmd {
|
||||
*/
|
||||
struct tcs_request {
|
||||
enum rpmh_state state;
|
||||
bool is_read;
|
||||
u32 wait_for_compl;
|
||||
u32 num_cmds;
|
||||
struct tcs_cmd *cmds;
|
||||
|
||||
Reference in New Issue
Block a user