diff mbox series

[v4,10/21] soc: qcom: rpmh-rsc: remaining U-Boot API changes

Message ID 20240709-b4-qcom-rpmh-v4-10-c06d0a26644a@linaro.org
State Superseded
Headers show
Series qcom: rpmh core and regulator support | expand

Commit Message

Caleb Connolly July 9, 2024, 9:34 a.m. UTC
Minor adjustments to fix building with U-Boot and work correctly as a
synchronous driver without interrupts. RPMh is fast enough that we can
get away with just firing off requests and assuming they complete.

U-Boot behaviour changes are annotated with a "U-Boot:" comment.

Signed-off-by: Caleb Connolly <caleb.connolly@linaro.org>
---
 drivers/soc/qcom/rpmh-rsc.c | 78 +++++++++++++++++----------------------------
 1 file changed, 29 insertions(+), 49 deletions(-)
diff mbox series

Patch

diff --git a/drivers/soc/qcom/rpmh-rsc.c b/drivers/soc/qcom/rpmh-rsc.c
index d4ef88dda184..566fa16baba9 100644
--- a/drivers/soc/qcom/rpmh-rsc.c
+++ b/drivers/soc/qcom/rpmh-rsc.c
@@ -134,16 +134,8 @@  enum {
  *  |                      ......                       |
  *  +---------------------------------------------------+
  */
 
-#define USECS_TO_CYCLES(time_usecs)			\
-	xloops_to_cycles((time_usecs) * 0x10C7UL)
-
-static inline unsigned long xloops_to_cycles(u64 xloops)
-{
-	return (xloops * loops_per_jiffy * HZ) >> 32;
-}
-
 static u32 rpmh_rsc_reg_offset_ver_2_7[] = {
 	[RSC_DRV_TCS_OFFSET]		= 672,
 	[RSC_DRV_CMD_OFFSET]		= 20,
 	[DRV_SOLVER_CONFIG]		= 0x04,
@@ -248,37 +240,18 @@  static void write_tcs_reg_sync(const struct rsc_drv *drv, int reg, int tcs_id,
  */
 static struct tcs_group *get_tcs_for_msg(struct rsc_drv *drv,
 					 const struct tcs_request *msg)
 {
-	int type;
-	struct tcs_group *tcs;
-
-	switch (msg->state) {
-	case RPMH_ACTIVE_ONLY_STATE:
-		type = ACTIVE_TCS;
-		break;
-	case RPMH_WAKE_ONLY_STATE:
-		type = WAKE_TCS;
-		break;
-	case RPMH_SLEEP_STATE:
-		type = SLEEP_TCS;
-		break;
-	default:
+	/*
+	 * U-Boot: since we're single threaded and running synchronously we can
+	 * just always used the first active TCS.
+	 */
+	if (msg->state != RPMH_ACTIVE_ONLY_STATE) {
+		log_err("WARN: only ACTIVE_ONLY state supported\n");
 		return ERR_PTR(-EINVAL);
 	}
 
-	/*
-	 * If we are making an active request on a RSC that does not have a
-	 * dedicated TCS for active state use, then re-purpose a wake TCS to
-	 * send active votes. This is safe because we ensure any active-only
-	 * transfers have finished before we use it (maybe by running from
-	 * the last CPU in PM code).
-	 */
-	tcs = &drv->tcs[type];
-	if (msg->state == RPMH_ACTIVE_ONLY_STATE && !tcs->num_tcs)
-		tcs = &drv->tcs[WAKE_TCS];
-
-	return tcs;
+	return &drv->tcs[ACTIVE_TCS];
 }
 
 /**
  * __tcs_buffer_write() - Write to TCS hardware from a request; don't trigger.
@@ -298,11 +271,8 @@  static void __tcs_buffer_write(struct rsc_drv *drv, int tcs_id, int cmd_id,
 	u32 cmd_enable = 0;
 	struct tcs_cmd *cmd;
 	int i, j;
 
-	/* Convert all commands to RR when the request has wait_for_compl set */
-	cmd_msgid |= msg->wait_for_compl ? CMD_MSGID_RESP_REQ : 0;
-
 	for (i = 0, j = cmd_id; i < msg->num_cmds; i++, j++) {
 		cmd = &msg->cmds[i];
 		cmd_enable |= BIT(j);
 		msgid = cmd_msgid;
@@ -314,9 +284,11 @@  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);
-		trace_rpmh_send_msg(drv, tcs_id, msg->state, j, msgid, cmd);
+		debug("tcs(m): %d [%s] cmd(n): %d msgid: %#x addr: %#x data: %#x complete: %d\n",
+		      tcs_id, msg->state == RPMH_ACTIVE_ONLY_STATE ? "active" : "?", j, msgid,
+		      cmd->addr, cmd->data, cmd->wait);
 	}
 
 	cmd_enable |= read_tcs_reg(drv, drv->regs[RSC_DRV_CMD_ENABLE], tcs_id);
 	write_tcs_reg(drv, drv->regs[RSC_DRV_CMD_ENABLE], tcs_id, cmd_enable);
@@ -346,34 +318,28 @@  static void __tcs_buffer_write(struct rsc_drv *drv, int tcs_id, int cmd_id,
  */
 int rpmh_rsc_send_data(struct rsc_drv *drv, const struct tcs_request *msg)
 {
 	struct tcs_group *tcs;
-	int tcs_id;
-
-	might_sleep();
+	int tcs_id, i;
+	u32 addr;
 
 	tcs = get_tcs_for_msg(drv, msg);
 	if (IS_ERR(tcs))
 		return PTR_ERR(tcs);
 
-	spin_lock_irq(&drv->lock);
-
-	/* Wait forever for a free tcs. It better be there eventually! */
-	wait_event_lock_irq(drv->tcs_wait,
-			    (tcs_id = claim_tcs_for_req(drv, tcs, msg)) >= 0,
-			    drv->lock);
+	/* u-boot is single-threaded, always use the first TCS as we'll never conflict */
+	tcs_id = tcs->offset;
 
 	tcs->req[tcs_id - tcs->offset] = msg;
-	set_bit(tcs_id, drv->tcs_in_use);
+	generic_set_bit(tcs_id, drv->tcs_in_use);
 	if (msg->state == RPMH_ACTIVE_ONLY_STATE && tcs->type != ACTIVE_TCS) {
 		/*
 		 * Clear previously programmed WAKE commands in selected
 		 * repurposed TCS to avoid triggering them. tcs->slots will be
 		 * cleaned from rpmh_flush() by invoking rpmh_rsc_invalidate()
 		 */
 		write_tcs_reg_sync(drv, drv->regs[RSC_DRV_CMD_ENABLE], tcs_id, 0);
 	}
-	spin_unlock_irq(&drv->lock);
 
 	/*
 	 * These two can be done after the lock is released because:
 	 * - We marked "tcs_in_use" under lock.
@@ -383,8 +349,22 @@  int rpmh_rsc_send_data(struct rsc_drv *drv, const struct tcs_request *msg)
 	 *   of __tcs_set_trigger() below.
 	 */
 	__tcs_buffer_write(drv, tcs_id, 0, msg);
 
+	/* U-Boot: Now wait for the TCS to be cleared, indicating that we're done */
+	for (i = 0; i < USEC_PER_SEC; i++) {
+		addr = read_tcs_cmd(drv, drv->regs[RSC_DRV_CMD_ADDR], i, 0);
+		if (addr != msg->cmds[0].addr)
+			break;
+		udelay(1);
+	}
+
+	if (i == USEC_PER_SEC) {
+		log_err("%s: error writing %#x to %d:%#x\n", drv->name,
+			msg->cmds[0].addr, tcs_id, drv->regs[RSC_DRV_CMD_ADDR]);
+		return -EINVAL;
+	}
+
 	return 0;
 }
 
 static int rpmh_probe_tcs_config(struct udevice *dev, struct rsc_drv *drv)