ASoC: cs35l41: Use polling for mail box

Use polling instead of interrupt for DSP mail box
acknowledgement.

With interrupt method, the amount of time for mail box
acknowledgement can vary, and sometimes long.

This is because interrupt handler reads all interrupt
status registers and masks, which can take long time,
especially on slow I2C bus.

Use polling to directly check for DSP mail box
acknowledgement reduces variability in amount of time
needed, because only 1 register is read.

Cirrus-JIRA-fixed: MMI-912
Change-Id: I21a223bbfdccb3593c61c7d04ae8355f2734c7a9
Signed-off-by: Li Xu <li-xu@outlook.com>
Signed-off-by: Yoon (Seungyoon) Lee <w22905@motorola.com>
Reviewed-on: https://gerrit.mot.com/1259695
SLTApproved: Slta Waiver
SME-Granted: SME Approvals Granted
Tested-by: Jira Key
Reviewed-by: Seungyoon Lee <yoon@motorola.com>
Submit-Approved: Jira Key
This commit is contained in:
Li Xu 2018-10-19 17:18:13 -05:00 • committed by Seungyoon Lee
commit b33af28110
3 changed files with 21 additions and 23 deletions

View file

@ -72,7 +72,6 @@ struct cs35l41_private {
struct gpio_desc *reset_gpio;
struct completion global_pup_done;
struct completion global_pdn_done;
struct completion mbox_cmd;
};
int cs35l41_probe(struct cs35l41_private *cs35l41,

View file

@ -254,8 +254,9 @@ static bool cs35l41_is_csplmboxsts_correct(enum cs35l41_cspl_mboxcmd cmd,
static int cs35l41_set_csplmboxcmd(struct cs35l41_private *cs35l41,
enum cs35l41_cspl_mboxcmd cmd)
{
int ret;
unsigned int sts;
int ret = 0;
unsigned int sts, i;
bool ack = false;
/* Reset DSP sticky bit */
regmap_write(cs35l41->regmap, CS35L41_IRQ2_STATUS2,
@ -268,26 +269,33 @@ static int cs35l41_set_csplmboxcmd(struct cs35l41_private *cs35l41,
/*
* Set mailbox cmd
*/
reinit_completion(&cs35l41->mbox_cmd);
/* Unmask DSP INT */
regmap_update_bits(cs35l41->regmap, CS35L41_IRQ2_MASK2,
1 << CS35L41_CSPL_MBOX_CMD_DRV_SHIFT, 0);
/* Unmask AP INT */
regmap_update_bits(cs35l41->regmap, CS35L41_IRQ1_MASK2,
1 << CS35L41_CSPL_MBOX_CMD_FW_SHIFT, 0);
regmap_write(cs35l41->regmap, CS35L41_CSPL_MBOX_CMD_DRV, cmd);
ret = wait_for_completion_timeout(&cs35l41->mbox_cmd,
msecs_to_jiffies(CS35L41_MBOXWAIT));
if (ret == 0) {
/* Poll for DSP ACK */
for (i = 0; i < 5; i++) {
usleep_range(1000, 1010);
regmap_read(cs35l41->regmap, CS35L41_IRQ1_STATUS2, &sts);
if (sts & (1 << CS35L41_CSPL_MBOX_CMD_FW_SHIFT)) {
dev_dbg(cs35l41->dev,
"%u: Received ACK in EINT for mbox cmd (%d)\n",
i, cmd);
regmap_write(cs35l41->regmap, CS35L41_IRQ1_STATUS2,
1 << CS35L41_CSPL_MBOX_CMD_FW_SHIFT);
ack = true;
break;
}
}
if (!ack) {
dev_err(cs35l41->dev,
"Timout waiting for DSP to set mbox cmd\n");
ret = -ETIMEDOUT;
}
/* Mask AP INT */
regmap_update_bits(cs35l41->regmap, CS35L41_IRQ1_MASK2,
1 << CS35L41_CSPL_MBOX_CMD_FW_SHIFT,
1 << CS35L41_CSPL_MBOX_CMD_FW_SHIFT);
/* Mask DSP INT */
regmap_update_bits(cs35l41->regmap, CS35L41_IRQ2_MASK2,
1 << CS35L41_CSPL_MBOX_CMD_DRV_SHIFT,
@ -641,12 +649,6 @@ static irqreturn_t cs35l41_irq(int irq, void *data)
!(status[2] & ~masks[2]) && !(status[3] & ~masks[3]))
return IRQ_NONE;
if (status[1] & (1 << CS35L41_CSPL_MBOX_CMD_FW_SHIFT)) {
regmap_write(cs35l41->regmap, CS35L41_IRQ1_STATUS2,
1 << CS35L41_CSPL_MBOX_CMD_FW_SHIFT);
complete(&cs35l41->mbox_cmd);
}
if (status[0] & CS35L41_PUP_DONE_MASK) {
regmap_write(cs35l41->regmap, CS35L41_IRQ1_STATUS1,
CS35L41_PUP_DONE_MASK);
@ -1925,8 +1927,6 @@ int cs35l41_probe(struct cs35l41_private *cs35l41,
init_completion(&cs35l41->global_pdn_done);
init_completion(&cs35l41->global_pup_done);
init_completion(&cs35l41->mbox_cmd);
ret = devm_request_threaded_irq(cs35l41->dev, cs35l41->irq, NULL,
cs35l41_irq, IRQF_ONESHOT | irq_pol,
"cs35l41", cs35l41);

View file

@ -736,7 +736,6 @@ extern const struct cs35l41_otp_map_element_t
cs35l41_otp_map_map[CS35L41_NUM_OTP_MAPS];
#define CS35L41_REGSTRIDE 4
#define CS35L41_MBOXWAIT 5
#define CS35L41_DSP_VIRT1_MBOX_SHIFT 20
#define CS35L41_DSP_VIRT2_MBOX_SHIFT 21