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:
Lina Iyer 2020-10-05 11:06:44 -06:00 committed by Maulik Shah
parent 419d3f8049
commit ad5eb0a49a
2 changed files with 95 additions and 1 deletions

View File

@ -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__ */

View File

@ -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)
{