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

Commit 0dc1d186 authored by Yan He's avatar Yan He Committed by Ravit Katzav
Browse files

msm: sps: check the BAM clock status before access a BAM



BAM could be clock gated when apps side is active. Thus, callback
the BAM client to confirm clocks are on before access the BAM. Also
provide the option for client driver to process the BAM IRQ after
the clocks are turned on.

Change-Id: I71682296e4dde3963b338eb65791ff8013495021
Signed-off-by: default avatarYan He <yanhe@codeaurora.org>
parent df66539f
Loading
Loading
Loading
Loading
+26 −0
Original line number Diff line number Diff line
@@ -2340,6 +2340,32 @@ int sps_pipe_reset(unsigned long dev, u32 pipe)
}
EXPORT_SYMBOL(sps_pipe_reset);

/*
 * Process any pending IRQ of a BAM
 */
int sps_bam_process_irq(unsigned long dev)
{
	struct sps_bam *bam;

	SPS_DBG("sps:%s.", __func__);

	if (!dev) {
		SPS_ERR("sps:%s:BAM handle is NULL.\n", __func__);
		return SPS_ERROR;
	}

	bam = sps_h2bam(dev);
	if (bam == NULL) {
		SPS_ERR("sps:%s:BAM is not found by handle.\n", __func__);
		return SPS_ERROR;
	}

	sps_bam_check_irq(bam);

	return 0;
}
EXPORT_SYMBOL(sps_bam_process_irq);

/**
 * Allocate client state context
 *
+72 −17
Original line number Diff line number Diff line
@@ -118,22 +118,17 @@ int sps_bam_driver_init(u32 options)
	return 0;
}

/**
 * BAM interrupt service routine
 *
 * This function is the BAM interrupt service routine.
 *
 * @ctxt - pointer to ISR's registered argument
 *
 * @return void
/*
 * Check BAM interrupt
 */
static irqreturn_t bam_isr(int irq, void *ctxt)
int sps_bam_check_irq(struct sps_bam *dev)
{
	struct sps_bam *dev = ctxt;
	struct sps_pipe *pipe;
	u32 source;
	unsigned long flags = 0;
	int ret = 0;

	SPS_DBG1("sps:%s:bam=%pa.\n", __func__, BAM_ID(dev));

	spin_lock_irqsave(&dev->isr_lock, flags);

@@ -144,11 +139,11 @@ static irqreturn_t bam_isr(int irq, void *ctxt)
		source = bam_check_irq_source(dev->base, dev->props.ee,
						mask, &cb_case);

		SPS_DBG1("sps:bam_isr:bam=%pa;source=0x%x;mask=0x%x.\n",
		SPS_DBG1("sps:bam=%pa;source=0x%x;mask=0x%x.\n",
				BAM_ID(dev), source, mask);

		if ((source & (1UL << 31)) && (dev->props.callback)) {
			SPS_DBG1("sps:bam_isr:bam=%pa;callback for case %d.\n",
			SPS_DBG1("sps:bam=%pa;callback for case %d.\n",
				BAM_ID(dev), cb_case);
			dev->props.callback(cb_case, dev->props.user);
		}
@@ -159,7 +154,7 @@ static irqreturn_t bam_isr(int irq, void *ctxt)
		/* If MTIs are used, must poll each active pipe */
		source = dev->pipe_active_mask;

		SPS_DBG1("sps:bam_isr for MTI:bam=%pa;source=0x%x.\n",
		SPS_DBG1("sps:MTI:bam=%pa;source=0x%x.\n",
				BAM_ID(dev), source);
	}

@@ -188,6 +183,50 @@ static irqreturn_t bam_isr(int irq, void *ctxt)

	spin_unlock_irqrestore(&dev->isr_lock, flags);

	return ret;
}

/**
 * BAM interrupt service routine
 *
 * This function is the BAM interrupt service routine.
 *
 * @ctxt - pointer to ISR's registered argument
 *
 * @return void
 */
static irqreturn_t bam_isr(int irq, void *ctxt)
{
	struct sps_bam *dev = ctxt;

	SPS_DBG1("sps:bam_isr: bam:%pa; IRQ #:%d.\n",
		BAM_ID(dev), irq);

	if (dev->props.options & SPS_BAM_RES_CONFIRM) {
		if (dev->props.callback) {
			bool ready = false;
			dev->props.callback(SPS_CALLBACK_BAM_RES_REQ, &ready);
			if (ready) {
				SPS_DBG1(
					"sps:bam_isr: handle IRQ for bam:%pa IRQ #:%d.\n",
					BAM_ID(dev), irq);
				sps_bam_check_irq(dev);
				dev->props.callback(SPS_CALLBACK_BAM_RES_REL,
							&ready);
			} else {
				SPS_DBG1(
					"sps:bam_isr: BAM is not ready and thus skip IRQ for bam:%pa IRQ #:%d.\n",
					BAM_ID(dev), irq);
			}
		} else {
			SPS_ERR(
				"sps:Client of BAM %pa requires confirmation but does not register callback\n",
				BAM_ID(dev));
		}
	} else {
		sps_bam_check_irq(dev);
	}

	return IRQ_HANDLED;
}

@@ -220,10 +259,26 @@ int sps_bam_enable(struct sps_bam *dev)
		dev->state &= ~BAM_STATE_IRQ;
	} else {
		/* Register BAM ISR */
		if (dev->props.irq > 0)
		if (dev->props.irq > 0) {
			if (dev->props.options & SPS_BAM_RES_CONFIRM) {
				result = request_irq(dev->props.irq,
					(irq_handler_t) bam_isr,
					IRQF_TRIGGER_RISING, "sps", dev);
				SPS_DBG(
					"sps:BAM %pa uses edge for IRQ# %d\n",
					BAM_ID(dev), dev->props.irq);
			} else {
				result = request_irq(dev->props.irq,
					(irq_handler_t) bam_isr,
					IRQF_TRIGGER_HIGH, "sps", dev);
				SPS_DBG(
					"sps:BAM %pa uses level for IRQ# %d\n",
					BAM_ID(dev), dev->props.irq);
			}
		} else {
			SPS_DBG1("sps:BAM %pa does not have an vaild IRQ# %d\n",
				BAM_ID(dev), dev->props.irq);
		}

		if (result) {
			SPS_ERR("sps:Failed to enable BAM %pa IRQ %d\n",
+9 −0
Original line number Diff line number Diff line
@@ -569,4 +569,13 @@ int sps_bam_pipe_timer_ctrl(struct sps_bam *dev, u32 pipe_index,
int sps_bam_pipe_get_unused_desc_num(struct sps_bam *dev, u32 pipe_index,
					u32 *desc_num);

/*
 * sps_bam_check_irq - check IRQ of a BAM device.
 * @dev - pointer to BAM device descriptor
 *
 * This function checks any pending interrupt of a BAM device.
 *
 * Return: 0 on success, negative value on error
 */
int sps_bam_check_irq(struct sps_bam *dev);
#endif	/* _SPSBAM_H_ */
+19 −1
Original line number Diff line number Diff line
@@ -109,7 +109,8 @@
#define SPS_BAM_NO_LOCAL_CLK_GATING (1UL << 5)
/* Don't enable writeback cancel*/
#define SPS_BAM_CANCEL_WB           (1UL << 6)

/* Confirm resource status before access BAM*/
#define SPS_BAM_RES_CONFIRM         (1UL << 7)

/* BAM device management flags */

@@ -296,6 +297,8 @@ enum sps_callback_case {
	SPS_CALLBACK_BAM_ERROR_IRQ = 1,     /* BAM ERROR IRQ */
	SPS_CALLBACK_BAM_HRESP_ERR_IRQ,	    /* Erroneous HResponse */
	SPS_CALLBACK_BAM_TIMER_IRQ,	    /* Inactivity timer */
	SPS_CALLBACK_BAM_RES_REQ,	    /* Request resource */
	SPS_CALLBACK_BAM_RES_REL,	    /* Release resource */
};

/*
@@ -1358,6 +1361,16 @@ int sps_ctrl_bam_dma_clk(bool clk_on);
 * Return: 0 on success, negative value on error
 */
int sps_pipe_reset(unsigned long dev, u32 pipe);

/*
 * sps_bam_process_irq - process IRQ of a BAM.
 * @dev:	BAM device handle
 *
 * This function processes any pending IRQ of a BAM.
 *
 * Return: 0 on success, negative value on error
 */
int sps_bam_process_irq(unsigned long dev);
#else
static inline int sps_register_bam_device(const struct sps_bam_props
			*bam_props, unsigned long *dev_handle)
@@ -1530,6 +1543,11 @@ static inline int sps_pipe_reset(unsigned long dev, u32 pipe)
{
	return -EPERM;
}

static inline int sps_bam_process_irq(unsigned long dev)
{
	return -EPERM;
}
#endif

#endif /* _SPS_H_ */