mirror of
https://github.com/torvalds/linux.git
synced 2026-07-31 11:37:06 +02:00
soc: qcom: rpmh-rsc: Add fast-path request support
In order to support lockless RPMh request, let's dedicate a TCS for this
purpose. This TCS shall be defined as FAST_PATH_TCS in the TCS
configuration for the RSC.
The fast-path TCS will have the following properties -
- A single TCS shall be defined as a fast-path TCS.
- Fast-path TCS will not use interrupt for signalling request
completion.
- Fast path will poll controller status for idle before sending request.
- DRV properties are not updated during the fast-path use.
- Fast path requests must be first initialized with {addr, data}.
- Subsequent updates will only update the data in the TCS and trigger.
- Requests must be fire-n-forget only (no completion).
Change-Id: I235ea60159e40affa9ce1e4069e11eca3925a423
Signed-off-by: Lina Iyer <ilina@codeaurora.org>
Signed-off-by: Maulik Shah <quic_mkshah@quicinc.com>
This commit is contained in:
parent
419d3f8049
commit
ad5eb0a49a
|
|
@ -11,7 +11,7 @@
|
|||
#include <linux/wait.h>
|
||||
#include <soc/qcom/tcs.h>
|
||||
|
||||
#define TCS_TYPE_NR 4
|
||||
#define TCS_TYPE_NR 5
|
||||
#define MAX_CMDS_PER_TCS 16
|
||||
#define MAX_TCS_PER_TYPE 3
|
||||
#define MAX_TCS_NR (MAX_TCS_PER_TYPE * TCS_TYPE_NR)
|
||||
|
|
@ -153,4 +153,9 @@ void rpmh_tx_done(const struct tcs_request *msg, int r);
|
|||
int rpmh_flush(struct rpmh_ctrlr *ctrlr);
|
||||
int _rpmh_flush(struct rpmh_ctrlr *ctrlr);
|
||||
|
||||
int rpmh_rsc_init_fast_path(struct rsc_drv *drv, const struct tcs_request *msg);
|
||||
int rpmh_rsc_update_fast_path(struct rsc_drv *drv,
|
||||
const struct tcs_request *msg,
|
||||
u32 update_mask);
|
||||
|
||||
#endif /* __RPM_INTERNAL_H__ */
|
||||
|
|
|
|||
|
|
@ -876,6 +876,11 @@ static bool rpmh_rsc_ctrlr_is_busy(struct rsc_drv *drv)
|
|||
max = tcs->offset + tcs->num_tcs;
|
||||
set = find_next_bit(drv->tcs_in_use, max, tcs->offset);
|
||||
|
||||
/* Check if there is pending fastpath transaction */
|
||||
if (drv->tcs[FAST_PATH_TCS].num_tcs &&
|
||||
!read_tcs_reg(drv, RSC_DRV_STATUS, drv->tcs[FAST_PATH_TCS].offset))
|
||||
return true;
|
||||
|
||||
return set < max;
|
||||
}
|
||||
|
||||
|
|
@ -985,6 +990,90 @@ int rpmh_rsc_mode_solver_set(struct rsc_drv *drv, bool enable)
|
|||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* rpmh_rsc_init_fast_path() - Initialize the fast-path TCS contents
|
||||
* @drv: The controller.
|
||||
* @msg: The TCS request to populate.
|
||||
*
|
||||
* Return:
|
||||
* * 0 - success
|
||||
* * -ENODEV - no fast-path TCS available
|
||||
*/
|
||||
int rpmh_rsc_init_fast_path(struct rsc_drv *drv, const struct tcs_request *msg)
|
||||
{
|
||||
int tcs_id;
|
||||
|
||||
if (!drv->tcs[FAST_PATH_TCS].num_tcs)
|
||||
return -ENODEV;
|
||||
|
||||
tcs_id = drv->tcs[FAST_PATH_TCS].offset;
|
||||
|
||||
/* We won't use the AMC IRQ to confirm if the TCS is free */
|
||||
enable_tcs_irq(drv, tcs_id, false);
|
||||
|
||||
__tcs_buffer_write(drv, tcs_id, 0, msg);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* rpmh_rsc_update_fast_path() - Update the fast-path TCS data and trigger
|
||||
* @drv: The controller.
|
||||
* @msg: The TCS request data to be updated.
|
||||
* @mask: The update mask for elements in @msg to be sent
|
||||
*
|
||||
* NOTE: Caller should ensure serialization before making this call.
|
||||
* Return:
|
||||
* * 0 - success
|
||||
* * -ENODEV - no fast-path TCS available
|
||||
*/
|
||||
int rpmh_rsc_update_fast_path(struct rsc_drv *drv,
|
||||
const struct tcs_request *msg,
|
||||
u32 mask)
|
||||
{
|
||||
int i;
|
||||
u32 sts;
|
||||
int tcs_id;
|
||||
struct tcs_cmd *cmd;
|
||||
int retry = 5;
|
||||
|
||||
if (!drv->tcs[FAST_PATH_TCS].num_tcs)
|
||||
return -ENODEV;
|
||||
|
||||
tcs_id = drv->tcs[FAST_PATH_TCS].offset;
|
||||
|
||||
/* Ensure the TCS is free before writing to the TCS */
|
||||
do {
|
||||
sts = read_tcs_reg(drv, RSC_DRV_STATUS, tcs_id);
|
||||
if (!sts) {
|
||||
retry--;
|
||||
/* Report and bail, if it took too many attempts */
|
||||
if (!retry) {
|
||||
pr_err("Fast-path TCS is too busy\n");
|
||||
return -EBUSY;
|
||||
}
|
||||
udelay(1);
|
||||
}
|
||||
} while (!sts);
|
||||
|
||||
/*
|
||||
* We only update the data, everything else remains the same.
|
||||
* The number of commands and the addresses do not change with
|
||||
* updates.
|
||||
*/
|
||||
for (i = 0; i < msg->num_cmds; i++) {
|
||||
if (!(mask & BIT(i)))
|
||||
continue;
|
||||
cmd = &msg->cmds[i];
|
||||
write_tcs_cmd(drv, RSC_DRV_CMD_DATA, tcs_id, i, cmd->data);
|
||||
}
|
||||
|
||||
/* Trigger the TCS to send the request */
|
||||
__tcs_set_trigger(drv, tcs_id, true);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rpmh_probe_tcs_config(struct platform_device *pdev,
|
||||
struct rsc_drv *drv, void __iomem *base)
|
||||
{
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user