[PATCH v11 5/9] spi: cadence: Add Marvell xSPI interrupt changes
From: Witold Sadowski
Date: Wed Jul 24 2024 - 11:49:11 EST
It is possible that before enabling interrupt, interrupt bit will be
set. It might cause improper IRQ handler behaviour. To fix it, clear
interrupt bit before enabling interrupts. That behaviour is specific to
Marvell xSPI implementation.
In addition in Marvell xSPI interrupt must be cleared in two places -
xSPI itself, and Marvell overlay.
Signed-off-by: Witold Sadowski <wsadowski@xxxxxxxxxxx>
---
drivers/spi/spi-cadence-xspi.c | 28 ++++++++++++++++++++++++----
1 file changed, 24 insertions(+), 4 deletions(-)
diff --git a/drivers/spi/spi-cadence-xspi.c b/drivers/spi/spi-cadence-xspi.c
index c177bf4ba536..84a320186aaf 100644
--- a/drivers/spi/spi-cadence-xspi.c
+++ b/drivers/spi/spi-cadence-xspi.c
@@ -311,6 +311,7 @@ struct cdns_xspi_dev {
const struct cdns_xspi_driver_data *driver_data;
void (*sdma_handler)(struct cdns_xspi_dev *cdns_xspi);
+ void (*set_interrupts_handler)(struct cdns_xspi_dev *cdns_xspi, bool enabled);
};
static void cdns_xspi_reset_dll(struct cdns_xspi_dev *cdns_xspi)
@@ -472,6 +473,23 @@ static void cdns_xspi_set_interrupts(struct cdns_xspi_dev *cdns_xspi,
writel(intr_enable, cdns_xspi->iobase + CDNS_XSPI_INTR_ENABLE_REG);
}
+static void marvell_xspi_set_interrupts(struct cdns_xspi_dev *cdns_xspi,
+ bool enabled)
+{
+ u32 intr_enable;
+ u32 irq_status;
+
+ irq_status = readl(cdns_xspi->iobase + CDNS_XSPI_INTR_STATUS_REG);
+ writel(irq_status, cdns_xspi->iobase + CDNS_XSPI_INTR_STATUS_REG);
+
+ intr_enable = readl(cdns_xspi->iobase + CDNS_XSPI_INTR_ENABLE_REG);
+ if (enabled)
+ intr_enable |= CDNS_XSPI_INTR_MASK;
+ else
+ intr_enable &= ~CDNS_XSPI_INTR_MASK;
+ writel(intr_enable, cdns_xspi->iobase + CDNS_XSPI_INTR_ENABLE_REG);
+}
+
static int cdns_xspi_controller_init(struct cdns_xspi_dev *cdns_xspi)
{
u32 ctrl_ver;
@@ -489,7 +507,7 @@ static int cdns_xspi_controller_init(struct cdns_xspi_dev *cdns_xspi)
ctrl_features = readl(cdns_xspi->iobase + CDNS_XSPI_CTRL_FEATURES_REG);
cdns_xspi->hw_num_banks = FIELD_GET(CDNS_XSPI_NUM_BANKS, ctrl_features);
- cdns_xspi_set_interrupts(cdns_xspi, false);
+ cdns_xspi->set_interrupts_handler(cdns_xspi, false);
return 0;
}
@@ -604,7 +622,7 @@ static int cdns_xspi_send_stig_command(struct cdns_xspi_dev *cdns_xspi,
writel(FIELD_PREP(CDNS_XSPI_CTRL_WORK_MODE, CDNS_XSPI_WORK_MODE_STIG),
cdns_xspi->iobase + CDNS_XSPI_CTRL_CONFIG_REG);
- cdns_xspi_set_interrupts(cdns_xspi, true);
+ cdns_xspi->set_interrupts_handler(cdns_xspi, true);
cdns_xspi->sdma_error = false;
memset(cmd_regs, 0, sizeof(cmd_regs));
@@ -636,14 +654,14 @@ static int cdns_xspi_send_stig_command(struct cdns_xspi_dev *cdns_xspi,
wait_for_completion(&cdns_xspi->sdma_complete);
if (cdns_xspi->sdma_error) {
- cdns_xspi_set_interrupts(cdns_xspi, false);
+ cdns_xspi->set_interrupts_handler(cdns_xspi, false);
return -EIO;
}
cdns_xspi->sdma_handler(cdns_xspi);
}
wait_for_completion(&cdns_xspi->cmd_complete);
- cdns_xspi_set_interrupts(cdns_xspi, false);
+ cdns_xspi->set_interrupts_handler(cdns_xspi, false);
cmd_status = cdns_xspi_check_command_status(cdns_xspi);
if (cmd_status)
@@ -812,9 +830,11 @@ static int cdns_xspi_probe(struct platform_device *pdev)
if (cdns_xspi->driver_data->mrvl_hw_overlay) {
host->mem_ops = &marvell_xspi_mem_ops;
cdns_xspi->sdma_handler = &marvell_xspi_sdma_handle;
+ cdns_xspi->set_interrupts_handler = &marvell_xspi_set_interrupts;
} else {
host->mem_ops = &cadence_xspi_mem_ops;
cdns_xspi->sdma_handler = &cdns_xspi_sdma_handle;
+ cdns_xspi->set_interrupts_handler = &cdns_xspi_set_interrupts;
}
host->dev.of_node = pdev->dev.of_node;
host->bus_num = -1;
--
2.43.0