]> www.infradead.org Git - linux.git/commitdiff
spi: cadence: Add Marvell xSPI interrupt changes
authorWitold Sadowski <wsadowski@marvell.com>
Wed, 24 Jul 2024 15:47:35 +0000 (08:47 -0700)
committerMark Brown <broonie@kernel.org>
Mon, 29 Jul 2024 00:19:28 +0000 (01:19 +0100)
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@marvell.com>
Link: https://patch.msgid.link/20240724154739.582367-6-wsadowski@marvell.com
Signed-off-by: Mark Brown <broonie@kernel.org>
drivers/spi/spi-cadence-xspi.c

index c177bf4ba5367c593063e9f09e7b32c31ad354bc..84a320186aaf18bf6a5ebbffd80e9114d11de907 100644 (file)
@@ -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;