Skip to content
Snippets Groups Projects
Commit a4a37e65 authored by Kamal Dasu's avatar Kamal Dasu Committed by Greg Kroah-Hartman
Browse files

spi: bcm-qspi: clear MSPI spifie interrupt during probe


commit 75b3cb97 upstream.

Intermittent Kernel crash has been observed on probe in
bcm_qspi_mspi_l2_isr() handler when the MSPI spifie interrupt bit
has not been cleared before registering for interrupts.
Fix the driver to move SoC specific custom interrupt handling code
before we register IRQ in probe. Also clear MSPI interrupt status
resgiter prior to registering IRQ handlers.

Fixes: cc20a386 ("spi: iproc-qspi: Add Broadcom iProc SoCs support")
Signed-off-by: default avatarKamal Dasu <kdasu@broadcom.com>
Acked-by: default avatarFlorian Fainelli <f.fainelli@gmail.com>
Link: https://lore.kernel.org/r/20211008203603.40915-3-kdasu.kdev@gmail.com


Signed-off-by: default avatarMark Brown <broonie@kernel.org>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent d9428f08
No related branches found
No related tags found
No related merge requests found
......@@ -1250,10 +1250,14 @@ static void bcm_qspi_hw_init(struct bcm_qspi *qspi)
static void bcm_qspi_hw_uninit(struct bcm_qspi *qspi)
{
u32 status = bcm_qspi_read(qspi, MSPI, MSPI_MSPI_STATUS);
bcm_qspi_write(qspi, MSPI, MSPI_SPCR2, 0);
if (has_bspi(qspi))
bcm_qspi_write(qspi, MSPI, MSPI_WRITE_LOCK, 0);
/* clear interrupt */
bcm_qspi_write(qspi, MSPI, MSPI_MSPI_STATUS, status & ~1);
}
static const struct spi_controller_mem_ops bcm_qspi_mem_ops = {
......@@ -1397,6 +1401,47 @@ int bcm_qspi_probe(struct platform_device *pdev,
if (!qspi->dev_ids)
return -ENOMEM;
/*
* Some SoCs integrate spi controller (e.g., its interrupt bits)
* in specific ways
*/
if (soc_intc) {
qspi->soc_intc = soc_intc;
soc_intc->bcm_qspi_int_set(soc_intc, MSPI_DONE, true);
} else {
qspi->soc_intc = NULL;
}
if (qspi->clk) {
ret = clk_prepare_enable(qspi->clk);
if (ret) {
dev_err(dev, "failed to prepare clock\n");
goto qspi_probe_err;
}
qspi->base_clk = clk_get_rate(qspi->clk);
} else {
qspi->base_clk = MSPI_BASE_FREQ;
}
if (data->has_mspi_rev) {
rev = bcm_qspi_read(qspi, MSPI, MSPI_REV);
/* some older revs do not have a MSPI_REV register */
if ((rev & 0xff) == 0xff)
rev = 0;
}
qspi->mspi_maj_rev = (rev >> 4) & 0xf;
qspi->mspi_min_rev = rev & 0xf;
qspi->mspi_spcr3_sysclk = data->has_spcr3_sysclk;
qspi->max_speed_hz = qspi->base_clk / (bcm_qspi_spbr_min(qspi) * 2);
/*
* On SW resets it is possible to have the mask still enabled
* Need to disable the mask and clear the status while we init
*/
bcm_qspi_hw_uninit(qspi);
for (val = 0; val < num_irqs; val++) {
irq = -1;
name = qspi_irq_tab[val].irq_name;
......@@ -1433,38 +1478,6 @@ int bcm_qspi_probe(struct platform_device *pdev,
goto qspi_probe_err;
}
/*
* Some SoCs integrate spi controller (e.g., its interrupt bits)
* in specific ways
*/
if (soc_intc) {
qspi->soc_intc = soc_intc;
soc_intc->bcm_qspi_int_set(soc_intc, MSPI_DONE, true);
} else {
qspi->soc_intc = NULL;
}
ret = clk_prepare_enable(qspi->clk);
if (ret) {
dev_err(dev, "failed to prepare clock\n");
goto qspi_probe_err;
}
qspi->base_clk = clk_get_rate(qspi->clk);
if (data->has_mspi_rev) {
rev = bcm_qspi_read(qspi, MSPI, MSPI_REV);
/* some older revs do not have a MSPI_REV register */
if ((rev & 0xff) == 0xff)
rev = 0;
}
qspi->mspi_maj_rev = (rev >> 4) & 0xf;
qspi->mspi_min_rev = rev & 0xf;
qspi->mspi_spcr3_sysclk = data->has_spcr3_sysclk;
qspi->max_speed_hz = qspi->base_clk / (bcm_qspi_spbr_min(qspi) * 2);
bcm_qspi_hw_init(qspi);
init_completion(&qspi->mspi_done);
init_completion(&qspi->bspi_done);
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment