Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 21c17886 authored by Lina Iyer's avatar Lina Iyer
Browse files

drivers: mailbox: allow active votes to be sent using wake TCS



When a TCS mailbox does not have explicit TCSes to send active mode
commands (AMC), use wake TCS to send the active votes. Any TCS can be
configured to send active mode votes, but using the TCS in active mode
complicates TCS slot allocation.

By explicitly requesting RPMH_AWAKE_STATE, active mode request can be
made for a resource through a DRV that does not have a dedicated TCS in
AMC mode. A WAKE TCS will be used to send these active requests and the
resource is stored as a wake value. The wake vote will be sent everytime
the RSC wakes up from sleep, unless the invalidate command is sent to
the mailbox driver.

Change-Id: I2e7435d1451657f18b4331b02217750107fe9511
Signed-off-by: default avatarLina Iyer <ilina@codeaurora.org>
parent 15d6df37
Loading
Loading
Loading
Loading
+29 −4
Original line number Diff line number Diff line
@@ -282,6 +282,16 @@ static inline struct tcs_mbox *get_tcs_for_msg(struct tcs_drv *drv,
	case RPMH_ACTIVE_ONLY_STATE:
		type = ACTIVE_TCS;
		break;
	case RPMH_AWAKE_STATE:
		/*
		 * Awake state is only used when the DRV has no separate
		 * TCS for ACTIVE requests. Switch to WAKE TCS to send
		 * active votes. Otherwise, the caller should be explicit
		 * about the state.
		 */
		if (IS_ERR(get_tcs_of_type(drv, ACTIVE_TCS)))
			type = WAKE_TCS;
		break;
	}

	if (msg->is_read)
@@ -319,6 +329,7 @@ static irqreturn_t tcs_irq_handler(int irq, void *p)
	void __iomem *base = drv->reg_base;
	int m, i;
	u32 irq_status, sts;
	struct tcs_mbox *tcs;
	struct tcs_response *resp;
	u32 irq_clear = 0;
	u32 data;
@@ -339,8 +350,20 @@ static irqreturn_t tcs_irq_handler(int irq, void *p)

		cancel_delayed_work(&resp->dwork);

		/* Clear the AMC mode for non-ACTIVE TCSes */
		tcs = get_tcs_from_index(drv, m);
		if (!tcs) {
			pr_err("TCS-%d doesn't exist in DRV\n", m);
			continue;
		}
		if (tcs->type != ACTIVE_TCS) {
			data = read_tcs_reg(base, TCS_DRV_CONTROL, m, 0);
			data &= ~TCS_AMC_MODE_ENABLE;
			write_tcs_reg(base, TCS_DRV_CONTROL, m, 0, data);
		} else {
			/* Clear the enable bit for the commands */
			write_tcs_reg(base, TCS_DRV_CMD_ENABLE, m, 0, 0);
		}

		/* Check if all commands were completed */
		resp->err = 0;
@@ -498,8 +521,9 @@ static bool tcs_drv_is_idle(struct mbox_controller *mbox)
	struct tcs_drv *drv = container_of(mbox, struct tcs_drv, mbox);
	struct tcs_mbox *tcs = get_tcs_of_type(drv, ACTIVE_TCS);

	/* Check for WAKE TCS if there are no ACTIVE TCS */
	if (IS_ERR(tcs))
		return true;
		tcs = get_tcs_of_type(drv, WAKE_TCS);

	for (m = tcs->tcs_offset; m < tcs->tcs_offset + tcs->num_tcs; m++)
		if (!tcs_is_free(drv->reg_base, m))
@@ -728,7 +752,8 @@ static int chan_tcs_write(struct mbox_chan *chan, void *data)
		goto tx_fail;
	}

	if (msg->state != RPMH_ACTIVE_ONLY_STATE) {
	if (msg->state != RPMH_ACTIVE_ONLY_STATE &&
			msg->state != RPMH_AWAKE_STATE) {
		dev_err(dev, "Incorrect API.\n");
		goto tx_fail;
	}
+1 −0
Original line number Diff line number Diff line
@@ -26,6 +26,7 @@ enum rpmh_state {
	RPMH_SLEEP_STATE,	/* Sleep */
	RPMH_WAKE_ONLY_STATE,	/* Wake only */
	RPMH_ACTIVE_ONLY_STATE,	/* Active only (= AMC) */
	RPMH_AWAKE_STATE,	/* Use Wake TCS for Wake & Active (AMC = 0) */
};

struct tcs_mbox_msg {