* [PATCH SPI for-next 0/3] DMA Support for SPI in PCI1xxxx
@ 2023-12-15 11:47 Thangaraj Samynathan
2023-12-15 11:47 ` [PATCH SPI for-next 1/3] spi: mchp-pci1xxxx: Add support for DMA in SPI Thangaraj Samynathan
` (2 more replies)
0 siblings, 3 replies; 8+ messages in thread
From: Thangaraj Samynathan @ 2023-12-15 11:47 UTC (permalink / raw)
To: broonie
Cc: linux-spi, linux-kernel, Tharunkumar.Pasumarthi,
Kumaravel.Thiagarajan, Arun.Ramadoss, Ronnie.Kunin,
jegadheesan.gopalmanoharan
This series of patches is to add DMA Support that improves SPI Performance
in PCI1xxxx. With DMA Support in 20MHz clock, the performance is improved
from 6Mbps to 17Mbps.
Thangaraj Samynathan (3):
spi: mchp-pci1xxxx: Add support for DMA in SPI
spi: mchp-pci1xxxx: DMA Read support for copying data into SPI Buf
spi: mchp-pci1xxxx: DMA Write Support for copying data from SPI Buf
drivers/spi/spi-pci1xxxx.c | 441 +++++++++++++++++++++++++++++++++++--
1 file changed, 419 insertions(+), 22 deletions(-)
--
2.25.1
^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH SPI for-next 1/3] spi: mchp-pci1xxxx: Add support for DMA in SPI
2023-12-15 11:47 [PATCH SPI for-next 0/3] DMA Support for SPI in PCI1xxxx Thangaraj Samynathan
@ 2023-12-15 11:47 ` Thangaraj Samynathan
2023-12-15 11:47 ` [PATCH SPI for-next 2/3] spi: mchp-pci1xxxx: DMA Read support for copying data into SPI Buf Thangaraj Samynathan
2023-12-15 11:47 ` [PATCH SPI for-next 3/3] spi: mchp-pci1xxxx: DMA Write Support for copying data from " Thangaraj Samynathan
2 siblings, 0 replies; 8+ messages in thread
From: Thangaraj Samynathan @ 2023-12-15 11:47 UTC (permalink / raw)
To: broonie
Cc: linux-spi, linux-kernel, Tharunkumar.Pasumarthi,
Kumaravel.Thiagarajan, Arun.Ramadoss, Ronnie.Kunin,
jegadheesan.gopalmanoharan
In PCI1xxxx C0, support for DMA in PCIe endpoint is added
to enhance the SPI performance. With this support, the
performance is improved from 6Mbps to 17Mbps with 20Mhz clock.
- DMA Supports two Channels, 0 and 1
- SPI Instance 0 uses chan 0 and SPI Instance 1 uses chan 1
- DMA can be used only if SPI is mapped to PF0 in the multi
function endpoint and the MSI interrupt is supported
- MSI interrupt of one of the SPI instance is assigned to the DMA
and both channels 0 and 1 share the same irq, the MSI address and
MSI Data of the irq is obtained and stored in DMA registers to
generate interrupt
Signed-off-by: Thangaraj Samynathan <thangaraj.s@microchip.com>
---
drivers/spi/spi-pci1xxxx.c | 135 +++++++++++++++++++++++++++++++++++++
1 file changed, 135 insertions(+)
diff --git a/drivers/spi/spi-pci1xxxx.c b/drivers/spi/spi-pci1xxxx.c
index 5b2d3e4e21b7..95b1255e62cd 100644
--- a/drivers/spi/spi-pci1xxxx.c
+++ b/drivers/spi/spi-pci1xxxx.c
@@ -5,7 +5,12 @@
// Kumaravel Thiagarajan <Kumaravel.Thiagarajan@microchip.com>
+#include <linux/dma-mapping.h>
+#include <linux/iopoll.h>
+#include <linux/irq.h>
#include <linux/module.h>
+#include <linux/msi.h>
+#include <linux/pci_regs.h>
#include <linux/pci.h>
#include <linux/spi/spi.h>
#include <linux/delay.h>
@@ -32,8 +37,33 @@
#define SPI_MST_CTL_MODE_SEL (BIT(2))
#define SPI_MST_CTL_GO (BIT(0))
+#define SPI_SYSTEM_ADDR_BASE (0x2000)
#define SPI_MST1_ADDR_BASE (0x800)
+#define DEV_REV_REG (SPI_SYSTEM_ADDR_BASE + 0x00)
+#define SPI_SYSLOCK_REG (SPI_SYSTEM_ADDR_BASE + 0xA0)
+#define SPI_CONFIG_PERI_ENABLE_REG (SPI_SYSTEM_ADDR_BASE + 0x108)
+
+#define SPI_PERI_ENBLE_PF_MASK (GENMASK(17, 16))
+#define DEV_REV_MASK (GENMASK(7, 0))
+
+#define SPI_SYSLOCK BIT(4)
+
+/* DMA Related Registers */
+#define SPI_DMA_ADDR_BASE (0x1000)
+#define SPI_DMA_GLOBAL_WR_ENGINE_EN (SPI_DMA_ADDR_BASE + 0x0C)
+#define SPI_DMA_GLOBAL_RD_ENGINE_EN (SPI_DMA_ADDR_BASE + 0x2C)
+#define SPI_DMA_INTR_IMWR_WDONE_LOW (SPI_DMA_ADDR_BASE + 0x60)
+#define SPI_DMA_INTR_IMWR_WDONE_HIGH (SPI_DMA_ADDR_BASE + 0x64)
+#define SPI_DMA_INTR_IMWR_WABORT_LOW (SPI_DMA_ADDR_BASE + 0x68)
+#define SPI_DMA_INTR_IMWR_WABORT_HIGH (SPI_DMA_ADDR_BASE + 0x6C)
+#define SPI_DMA_INTR_WR_IMWR_DATA (SPI_DMA_ADDR_BASE + 0x70)
+#define SPI_DMA_INTR_IMWR_RDONE_LOW (SPI_DMA_ADDR_BASE + 0xCC)
+#define SPI_DMA_INTR_IMWR_RDONE_HIGH (SPI_DMA_ADDR_BASE + 0xD0)
+#define SPI_DMA_INTR_IMWR_RABORT_LOW (SPI_DMA_ADDR_BASE + 0xD4)
+#define SPI_DMA_INTR_IMWR_RABORT_HIGH (SPI_DMA_ADDR_BASE + 0xD8)
+#define SPI_DMA_INTR_RD_IMWR_DATA (SPI_DMA_ADDR_BASE + 0xDC)
+
/* x refers to SPI Host Controller HW instance id in the below macros - 0 or 1 */
#define SPI_MST_CMD_BUF_OFFSET(x) (((x) * SPI_MST1_ADDR_BASE) + 0x00)
@@ -50,6 +80,8 @@
#define SPI_MAX_DATA_LEN 320
#define PCI1XXXX_SPI_TIMEOUT (msecs_to_jiffies(100))
+#define SYSLOCK_RETRY_CNT (1000)
+#define SPI_DMA_ENGINE_EN (0x1)
#define SPI_INTR BIT(8)
#define SPI_FORCE_CE BIT(4)
@@ -76,7 +108,10 @@ struct pci1xxxx_spi_internal {
struct pci1xxxx_spi {
struct pci_dev *dev;
u8 total_hw_instances;
+ u8 dev_rev;
void __iomem *reg_base;
+ void __iomem *dma_offset_bar;
+ bool can_dma;
struct pci1xxxx_spi_internal *spi_int[] __counted_by(total_hw_instances);
};
@@ -106,6 +141,102 @@ static const struct pci_device_id pci1xxxx_spi_pci_id_table[] = {
MODULE_DEVICE_TABLE(pci, pci1xxxx_spi_pci_id_table);
+static int pci1xxxx_set_sys_lock(struct pci1xxxx_spi *par)
+{
+ writel(SPI_SYSLOCK, par->reg_base + SPI_SYSLOCK_REG);
+ return readl(par->reg_base + SPI_SYSLOCK_REG);
+}
+
+static int pci1xxxx_acquire_sys_lock(struct pci1xxxx_spi *par)
+{
+ u32 regval;
+
+ return readx_poll_timeout(pci1xxxx_set_sys_lock, par, regval,
+ (regval & SPI_SYSLOCK), 100,
+ SYSLOCK_RETRY_CNT * 100);
+}
+
+static void pci1xxxx_release_sys_lock(struct pci1xxxx_spi *par)
+{
+ writel(0x0, par->reg_base + SPI_SYSLOCK_REG);
+}
+
+static int pci1xxxx_check_spi_can_dma(struct pci1xxxx_spi *spi_bus, int irq)
+{
+ struct pci_dev *pdev = spi_bus->dev;
+ u32 pf_num;
+ u32 regval;
+ int ret;
+
+ /*
+ * DEV REV Registers is a system register, HW Syslock bit
+ * should be acquired before accessing the register
+ */
+ ret = pci1xxxx_acquire_sys_lock(spi_bus);
+ if (ret)
+ return ret;
+
+ regval = readl(spi_bus->reg_base + DEV_REV_REG);
+ spi_bus->dev_rev = regval & DEV_REV_MASK;
+ if (spi_bus->dev_rev >= 0xC0) {
+ regval = readl(spi_bus->reg_base +
+ SPI_CONFIG_PERI_ENABLE_REG);
+ pf_num = regval & SPI_PERI_ENBLE_PF_MASK;
+ }
+
+ pci1xxxx_release_sys_lock(spi_bus);
+
+ /*
+ * DMA is supported only from C0 and SPI can use DMA only if
+ * it is mapped to PF0
+ */
+ if (spi_bus->dev_rev < 0xC0 || pf_num)
+ return -EOPNOTSUPP;
+
+ /*
+ * DMA Supported only with MSI Interrupts
+ * One of the SPI instance's MSI vector address and data
+ * is used for DMA Interrupt
+ */
+ if (!irq_get_msi_desc(irq))
+ return -EOPNOTSUPP;
+
+ spi_bus->dma_offset_bar = pcim_iomap(pdev, 2, pci_resource_len(pdev, 2));
+ if (!spi_bus->dma_offset_bar)
+ return -EOPNOTSUPP;
+
+ if (dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64)))
+ return -EOPNOTSUPP;
+
+ return 0;
+}
+
+static int pci1xxxx_spi_dma_init(struct pci1xxxx_spi *spi_bus, int irq)
+{
+ struct msi_msg msi;
+ int ret;
+
+ ret = pci1xxxx_check_spi_can_dma(spi_bus, irq);
+ if (ret)
+ return ret;
+
+ get_cached_msi_msg(irq, &msi);
+ writel(SPI_DMA_ENGINE_EN, spi_bus->dma_offset_bar + SPI_DMA_GLOBAL_WR_ENGINE_EN);
+ writel(SPI_DMA_ENGINE_EN, spi_bus->dma_offset_bar + SPI_DMA_GLOBAL_RD_ENGINE_EN);
+ writel(msi.address_hi, spi_bus->dma_offset_bar + SPI_DMA_INTR_IMWR_WDONE_HIGH);
+ writel(msi.address_hi, spi_bus->dma_offset_bar + SPI_DMA_INTR_IMWR_WABORT_HIGH);
+ writel(msi.address_hi, spi_bus->dma_offset_bar + SPI_DMA_INTR_IMWR_RDONE_HIGH);
+ writel(msi.address_hi, spi_bus->dma_offset_bar + SPI_DMA_INTR_IMWR_RABORT_HIGH);
+ writel(msi.address_lo, spi_bus->dma_offset_bar + SPI_DMA_INTR_IMWR_WDONE_LOW);
+ writel(msi.address_lo, spi_bus->dma_offset_bar + SPI_DMA_INTR_IMWR_WABORT_LOW);
+ writel(msi.address_lo, spi_bus->dma_offset_bar + SPI_DMA_INTR_IMWR_RDONE_LOW);
+ writel(msi.address_lo, spi_bus->dma_offset_bar + SPI_DMA_INTR_IMWR_RABORT_LOW);
+ writel(msi.data, spi_bus->dma_offset_bar + SPI_DMA_INTR_WR_IMWR_DATA);
+ writel(msi.data, spi_bus->dma_offset_bar + SPI_DMA_INTR_RD_IMWR_DATA);
+ spi_bus->can_dma = true;
+ return 0;
+}
+
static void pci1xxxx_spi_set_cs(struct spi_device *spi, bool enable)
{
struct pci1xxxx_spi_internal *p = spi_controller_get_devdata(spi->controller);
@@ -324,6 +455,10 @@ static int pci1xxxx_spi_probe(struct pci_dev *pdev, const struct pci_device_id *
goto error;
}
+ ret = pci1xxxx_spi_dma_init(spi_bus, spi_sub_ptr->irq);
+ if (ret && ret != -EOPNOTSUPP)
+ return ret;
+
/* This register is only applicable for 1st instance */
regval = readl(spi_bus->reg_base + SPI_PCI_CTRL_REG_OFFSET(0));
if (!only_sec_inst)
--
2.25.1
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH SPI for-next 2/3] spi: mchp-pci1xxxx: DMA Read support for copying data into SPI Buf
2023-12-15 11:47 [PATCH SPI for-next 0/3] DMA Support for SPI in PCI1xxxx Thangaraj Samynathan
2023-12-15 11:47 ` [PATCH SPI for-next 1/3] spi: mchp-pci1xxxx: Add support for DMA in SPI Thangaraj Samynathan
@ 2023-12-15 11:47 ` Thangaraj Samynathan
2023-12-15 13:29 ` Mark Brown
` (2 more replies)
2023-12-15 11:47 ` [PATCH SPI for-next 3/3] spi: mchp-pci1xxxx: DMA Write Support for copying data from " Thangaraj Samynathan
2 siblings, 3 replies; 8+ messages in thread
From: Thangaraj Samynathan @ 2023-12-15 11:47 UTC (permalink / raw)
To: broonie
Cc: linux-spi, linux-kernel, Tharunkumar.Pasumarthi,
Kumaravel.Thiagarajan, Arun.Ramadoss, Ronnie.Kunin,
jegadheesan.gopalmanoharan
pci1xxxx_spi_transfer_with_dma is registered as transfer_one callback
when DMA can be supported. This function adds DMA read operation which
copies the data from host cpu buffer to SPI Tx Buffer.
On DMA Read Completion interrupt, SPI transaction is initiated in isr.
Helper functions pci1xxxx_spi_setup, pci1xxxx_spi_setup_dma_read and
pci1xxxx_start_spi_xfer are added for starting spi transfer, setting up
spi and dma read operation. In the existing implementation, codes are
replaced with helper wherever applicable.
Signed-off-by: Thangaraj Samynathan <thangaraj.s@microchip.com>
---
drivers/spi/spi-pci1xxxx.c | 225 +++++++++++++++++++++++++++++++++----
1 file changed, 204 insertions(+), 21 deletions(-)
diff --git a/drivers/spi/spi-pci1xxxx.c b/drivers/spi/spi-pci1xxxx.c
index 95b1255e62cd..824885ada9b6 100644
--- a/drivers/spi/spi-pci1xxxx.c
+++ b/drivers/spi/spi-pci1xxxx.c
@@ -5,6 +5,7 @@
// Kumaravel Thiagarajan <Kumaravel.Thiagarajan@microchip.com>
+#include <linux/bitfield.h>
#include <linux/dma-mapping.h>
#include <linux/iopoll.h>
#include <linux/irq.h>
@@ -12,6 +13,7 @@
#include <linux/msi.h>
#include <linux/pci_regs.h>
#include <linux/pci.h>
+#include <linux/spinlock.h>
#include <linux/spi/spi.h>
#include <linux/delay.h>
@@ -37,6 +39,7 @@
#define SPI_MST_CTL_MODE_SEL (BIT(2))
#define SPI_MST_CTL_GO (BIT(0))
+#define SPI_PERI_ADDR_BASE (0x160000)
#define SPI_SYSTEM_ADDR_BASE (0x2000)
#define SPI_MST1_ADDR_BASE (0x800)
@@ -48,22 +51,49 @@
#define DEV_REV_MASK (GENMASK(7, 0))
#define SPI_SYSLOCK BIT(4)
+#define SPI0 (0)
+#define SPI1 (1)
/* DMA Related Registers */
#define SPI_DMA_ADDR_BASE (0x1000)
#define SPI_DMA_GLOBAL_WR_ENGINE_EN (SPI_DMA_ADDR_BASE + 0x0C)
#define SPI_DMA_GLOBAL_RD_ENGINE_EN (SPI_DMA_ADDR_BASE + 0x2C)
+#define SPI_DMA_RD_DOORBELL_REG (SPI_DMA_ADDR_BASE + 0x30)
#define SPI_DMA_INTR_IMWR_WDONE_LOW (SPI_DMA_ADDR_BASE + 0x60)
#define SPI_DMA_INTR_IMWR_WDONE_HIGH (SPI_DMA_ADDR_BASE + 0x64)
#define SPI_DMA_INTR_IMWR_WABORT_LOW (SPI_DMA_ADDR_BASE + 0x68)
#define SPI_DMA_INTR_IMWR_WABORT_HIGH (SPI_DMA_ADDR_BASE + 0x6C)
#define SPI_DMA_INTR_WR_IMWR_DATA (SPI_DMA_ADDR_BASE + 0x70)
+#define SPI_DMA_INTR_RD_STS (SPI_DMA_ADDR_BASE + 0xA0)
+#define SPI_DMA_RD_INT_MASK (SPI_DMA_ADDR_BASE + 0xA8)
+#define SPI_DMA_INTR_RD_CLR (SPI_DMA_ADDR_BASE + 0xAC)
+#define SPI_DMA_ERR_RD_STS (SPI_DMA_ADDR_BASE + 0xB8)
#define SPI_DMA_INTR_IMWR_RDONE_LOW (SPI_DMA_ADDR_BASE + 0xCC)
#define SPI_DMA_INTR_IMWR_RDONE_HIGH (SPI_DMA_ADDR_BASE + 0xD0)
#define SPI_DMA_INTR_IMWR_RABORT_LOW (SPI_DMA_ADDR_BASE + 0xD4)
#define SPI_DMA_INTR_IMWR_RABORT_HIGH (SPI_DMA_ADDR_BASE + 0xD8)
#define SPI_DMA_INTR_RD_IMWR_DATA (SPI_DMA_ADDR_BASE + 0xDC)
+#define SPI_DMA_CH0_RD_BASE (SPI_DMA_ADDR_BASE + 0x300)
+#define SPI_DMA_CH1_RD_BASE (SPI_DMA_ADDR_BASE + 0x500)
+
+#define SPI_DMA_CH_CTL1_OFFSET (0x00)
+#define SPI_DMA_CH_XFER_LEN_OFFSET (0x08)
+#define SPI_DMA_CH_SAR_LO_OFFSET (0x0C)
+#define SPI_DMA_CH_SAR_HI_OFFSET (0x10)
+#define SPI_DMA_CH_DAR_LO_OFFSET (0x14)
+#define SPI_DMA_CH_DAR_HI_OFFSET (0x18)
+
+#define SPI_DMA_CH0_DONE_INT BIT(0)
+#define SPI_DMA_CH1_DONE_INT BIT(1)
+#define SPI_DMA_CH0_ABORT_INT BIT(16)
+#define SPI_DMA_CH1_ABORT_INT BIT(17)
+#define SPI_DMA_DONE_INT_MASK (SPI_DMA_CH0_DONE_INT | SPI_DMA_CH1_DONE_INT)
+#define SPI_DMA_ABORT_INT_MASK (SPI_DMA_CH0_ABORT_INT | SPI_DMA_CH1_ABORT_INT)
+#define DMA_CH_CONTROL_LIE BIT(3)
+#define DMA_CH_CONTROL_RIE BIT(4)
+#define DMA_INTR_EN (DMA_CH_CONTROL_RIE | DMA_CH_CONTROL_LIE)
+
/* x refers to SPI Host Controller HW instance id in the below macros - 0 or 1 */
#define SPI_MST_CMD_BUF_OFFSET(x) (((x) * SPI_MST1_ADDR_BASE) + 0x00)
@@ -82,6 +112,7 @@
#define PCI1XXXX_SPI_TIMEOUT (msecs_to_jiffies(100))
#define SYSLOCK_RETRY_CNT (1000)
#define SPI_DMA_ENGINE_EN (0x1)
+#define SPI_DMA_ENGINE_DIS (0x0)
#define SPI_INTR BIT(8)
#define SPI_FORCE_CE BIT(4)
@@ -95,6 +126,7 @@
struct pci1xxxx_spi_internal {
u8 hw_inst;
bool spi_xfer_in_progress;
+ bool dma_aborted_rd;
int irq;
struct completion spi_xfer_done;
struct spi_controller *spi_host;
@@ -111,6 +143,8 @@ struct pci1xxxx_spi {
u8 dev_rev;
void __iomem *reg_base;
void __iomem *dma_offset_bar;
+ /* lock to safely access the DMA registers in isr */
+ spinlock_t dma_reg_lock;
bool can_dma;
struct pci1xxxx_spi_internal *spi_int[] __counted_by(total_hw_instances);
};
@@ -220,6 +254,7 @@ static int pci1xxxx_spi_dma_init(struct pci1xxxx_spi *spi_bus, int irq)
if (ret)
return ret;
+ spin_lock_init(&spi_bus->dma_reg_lock);
get_cached_msi_msg(irq, &msi);
writel(SPI_DMA_ENGINE_EN, spi_bus->dma_offset_bar + SPI_DMA_GLOBAL_WR_ENGINE_EN);
writel(SPI_DMA_ENGINE_EN, spi_bus->dma_offset_bar + SPI_DMA_GLOBAL_RD_ENGINE_EN);
@@ -277,6 +312,53 @@ static u8 pci1xxxx_get_clock_div(u32 hz)
return val;
}
+static void pci1xxxx_spi_setup_dma_read(struct pci1xxxx_spi_internal *p,
+ dma_addr_t dma_addr, u32 len)
+{
+ void *base;
+
+ if (!p->hw_inst)
+ base = p->parent->dma_offset_bar + SPI_DMA_CH0_RD_BASE;
+ else
+ base = p->parent->dma_offset_bar + SPI_DMA_CH1_RD_BASE;
+
+ writel(DMA_INTR_EN, base + SPI_DMA_CH_CTL1_OFFSET);
+ writel(len, base + SPI_DMA_CH_XFER_LEN_OFFSET);
+ writel(lower_32_bits(dma_addr), base + SPI_DMA_CH_SAR_LO_OFFSET);
+ writel(upper_32_bits(dma_addr), base + SPI_DMA_CH_SAR_HI_OFFSET);
+ /* Updated SPI Command Registers */
+ writel(lower_32_bits(SPI_PERI_ADDR_BASE + SPI_MST_CMD_BUF_OFFSET(p->hw_inst)),
+ base + SPI_DMA_CH_DAR_LO_OFFSET);
+ writel(upper_32_bits(SPI_PERI_ADDR_BASE + SPI_MST_CMD_BUF_OFFSET(p->hw_inst)),
+ base + SPI_DMA_CH_DAR_HI_OFFSET);
+}
+
+static void pci1xxxx_spi_setup(struct pci1xxxx_spi *par, u8 hw_inst, u32 mode,
+ u8 clkdiv, u32 len)
+{
+ u32 regval;
+
+ regval = readl(par->reg_base + SPI_MST_CTL_REG_OFFSET(hw_inst));
+ regval &= ~(SPI_MST_CTL_MODE_SEL | SPI_MST_CTL_CMD_LEN_MASK |
+ SPI_MST_CTL_SPEED_MASK);
+
+ if (mode == SPI_MODE_3)
+ regval |= SPI_MST_CTL_MODE_SEL;
+
+ regval |= FIELD_PREP(SPI_MST_CTL_CMD_LEN_MASK, len);
+ regval |= FIELD_PREP(SPI_MST_CTL_SPEED_MASK, clkdiv);
+ writel(regval, par->reg_base + SPI_MST_CTL_REG_OFFSET(hw_inst));
+}
+
+static void pci1xxxx_start_spi_xfer(struct pci1xxxx_spi_internal *p, u8 hw_inst)
+{
+ u32 regval;
+
+ regval = readl(p->parent->reg_base + SPI_MST_CTL_REG_OFFSET(hw_inst));
+ regval |= SPI_MST_CTL_GO;
+ writel(regval, p->parent->reg_base + SPI_MST_CTL_REG_OFFSET(hw_inst));
+}
+
static int pci1xxxx_spi_transfer_one(struct spi_controller *spi_ctlr,
struct spi_device *spi, struct spi_transfer *xfer)
{
@@ -317,26 +399,8 @@ static int pci1xxxx_spi_transfer_one(struct spi_controller *spi_ctlr,
memcpy_toio(par->reg_base + SPI_MST_CMD_BUF_OFFSET(p->hw_inst),
&tx_buf[bytes_transfered], len);
bytes_transfered += len;
- regval = readl(par->reg_base +
- SPI_MST_CTL_REG_OFFSET(p->hw_inst));
- regval &= ~(SPI_MST_CTL_MODE_SEL | SPI_MST_CTL_CMD_LEN_MASK |
- SPI_MST_CTL_SPEED_MASK);
-
- if (mode == SPI_MODE_3)
- regval |= SPI_MST_CTL_MODE_SEL;
- else
- regval &= ~SPI_MST_CTL_MODE_SEL;
-
- regval |= (clkdiv << 5);
- regval &= ~SPI_MST_CTL_CMD_LEN_MASK;
- regval |= (len << 8);
- writel(regval, par->reg_base +
- SPI_MST_CTL_REG_OFFSET(p->hw_inst));
- regval = readl(par->reg_base +
- SPI_MST_CTL_REG_OFFSET(p->hw_inst));
- regval |= SPI_MST_CTL_GO;
- writel(regval, par->reg_base +
- SPI_MST_CTL_REG_OFFSET(p->hw_inst));
+ pci1xxxx_spi_setup(par, p->hw_inst, spi->mode, clkdiv, len);
+ pci1xxxx_start_spi_xfer(p, p->hw_inst);
/* Wait for DMA_TERM interrupt */
result = wait_for_completion_timeout(&p->spi_xfer_done,
@@ -356,10 +420,105 @@ static int pci1xxxx_spi_transfer_one(struct spi_controller *spi_ctlr,
return 0;
}
+static int pci1xxxx_spi_transfer_with_dma(struct spi_controller *spi_ctlr,
+ struct spi_device *spi,
+ struct spi_transfer *xfer)
+{
+ struct pci1xxxx_spi_internal *p = spi_controller_get_devdata(spi_ctlr);
+ struct pci1xxxx_spi *par = p->parent;
+ struct device *dev = &par->dev->dev;
+ dma_addr_t tx_dma_addr = 0;
+ u64 bytes_transfered = 0;
+ u64 bytes_recvd = 0;
+ int loop_count;
+ int ret = 0;
+ u32 regval;
+ u8 *rx_buf;
+ u8 clkdiv;
+ u32 len;
+ u32 i;
+
+ p->spi_xfer_in_progress = true;
+ clkdiv = pci1xxxx_get_clock_div(xfer->speed_hz);
+ rx_buf = xfer->rx_buf;
+ regval = readl(par->reg_base + SPI_MST_EVENT_REG_OFFSET(p->hw_inst));
+ writel(regval, par->reg_base + SPI_MST_EVENT_REG_OFFSET(p->hw_inst));
+
+ if (!xfer->tx_buf) {
+ ret = -EINVAL;
+ goto error;
+ }
+
+ tx_dma_addr = dma_map_single(dev, (void *)xfer->tx_buf, xfer->len, DMA_TO_DEVICE);
+ if (dma_mapping_error(NULL, tx_dma_addr)) {
+ tx_dma_addr = 0;
+ ret = -ENOMEM;
+ goto error;
+ }
+
+ loop_count = DIV_ROUND_UP(xfer->len, SPI_MAX_DATA_LEN);
+ len = SPI_MAX_DATA_LEN;
+ pci1xxxx_spi_setup(par, p->hw_inst, spi->mode, clkdiv, len);
+ for (i = 0; i < loop_count; i++) {
+ if ((i == loop_count - 1) && (xfer->len % SPI_MAX_DATA_LEN != 0)) {
+ len = xfer->len % SPI_MAX_DATA_LEN;
+ pci1xxxx_spi_setup(par, p->hw_inst, spi->mode, clkdiv, len);
+ }
+
+ pci1xxxx_spi_setup_dma_read(p, (tx_dma_addr + bytes_transfered), len);
+
+ writel(p->hw_inst, par->dma_offset_bar + SPI_DMA_RD_DOORBELL_REG);
+
+ reinit_completion(&p->spi_xfer_done);
+ /* Wait for DMA_TERM interrupt */
+ ret = wait_for_completion_timeout(&p->spi_xfer_done, PCI1XXXX_SPI_TIMEOUT);
+ if (!ret) {
+ ret = -ETIMEDOUT;
+ if (p->dma_aborted_rd) {
+ writel(SPI_DMA_ENGINE_DIS,
+ par->dma_offset_bar + SPI_DMA_GLOBAL_RD_ENGINE_EN);
+
+ /*
+ * DMA ENGINE reset takes time if any TLP
+ * completeion in progress, should wait
+ * till DMA Engine reset is completed.
+ */
+ ret = readl_poll_timeout(par->dma_offset_bar +
+ SPI_DMA_GLOBAL_RD_ENGINE_EN, regval,
+ (regval == 0x0), 0, USEC_PER_MSEC);
+ if (ret) {
+ ret = -ECANCELED;
+ goto error;
+ }
+ writel(SPI_DMA_ENGINE_EN,
+ par->dma_offset_bar + SPI_DMA_GLOBAL_RD_ENGINE_EN);
+ p->dma_aborted_rd = false;
+ ret = -ECANCELED;
+ }
+ goto error;
+ }
+ bytes_transfered += len;
+ if (rx_buf) {
+ memcpy_fromio(&rx_buf[bytes_recvd], par->reg_base +
+ SPI_MST_RSP_BUF_OFFSET(p->hw_inst), len);
+ bytes_recvd += len;
+ }
+ ret = 0;
+ }
+
+error:
+ p->spi_xfer_in_progress = false;
+ if (tx_dma_addr)
+ dma_unmap_single(dev, tx_dma_addr, xfer->len, DMA_TO_DEVICE);
+
+ return ret;
+}
+
static irqreturn_t pci1xxxx_spi_isr(int irq, void *dev)
{
struct pci1xxxx_spi_internal *p = dev;
irqreturn_t spi_int_fired = IRQ_NONE;
+ unsigned long flags;
u32 regval;
/* Clear the SPI GO_BIT Interrupt */
@@ -372,6 +531,26 @@ static irqreturn_t pci1xxxx_spi_isr(int irq, void *dev)
writel(regval, p->parent->reg_base + SPI_MST_EVENT_REG_OFFSET(p->hw_inst));
+ if (!p->parent->can_dma)
+ return spi_int_fired;
+
+ spin_lock_irqsave(&p->parent->dma_reg_lock, flags);
+ /* Clear the DMA RD INT and start spi xfer*/
+ regval = readl(p->parent->dma_offset_bar + SPI_DMA_INTR_RD_STS);
+ if (regval & SPI_DMA_DONE_INT_MASK) {
+ if (regval & SPI_DMA_CH0_DONE_INT)
+ pci1xxxx_start_spi_xfer(p, SPI0);
+ if (regval & SPI_DMA_CH1_DONE_INT)
+ pci1xxxx_start_spi_xfer(p, SPI1);
+ spi_int_fired = IRQ_HANDLED;
+ }
+ if (regval & SPI_DMA_ABORT_INT_MASK) {
+ p->dma_aborted_rd = true;
+ spi_int_fired = IRQ_HANDLED;
+ }
+ writel(regval, p->parent->dma_offset_bar + SPI_DMA_INTR_RD_CLR);
+ spin_unlock_irqrestore(&p->parent->dma_reg_lock, flags);
+
return spi_int_fired;
}
@@ -495,7 +674,11 @@ static int pci1xxxx_spi_probe(struct pci_dev *pdev, const struct pci_device_id *
spi_host->num_chipselect = SPI_CHIP_SEL_COUNT;
spi_host->mode_bits = SPI_MODE_0 | SPI_MODE_3 | SPI_RX_DUAL |
SPI_TX_DUAL | SPI_LOOP;
- spi_host->transfer_one = pci1xxxx_spi_transfer_one;
+ if (spi_bus->can_dma)
+ spi_host->transfer_one = pci1xxxx_spi_transfer_with_dma;
+ else
+ spi_host->transfer_one = pci1xxxx_spi_transfer_one;
+
spi_host->set_cs = pci1xxxx_spi_set_cs;
spi_host->bits_per_word_mask = SPI_BPW_MASK(8);
spi_host->max_speed_hz = PCI1XXXX_SPI_MAX_CLOCK_HZ;
--
2.25.1
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH SPI for-next 3/3] spi: mchp-pci1xxxx: DMA Write Support for copying data from SPI Buf
2023-12-15 11:47 [PATCH SPI for-next 0/3] DMA Support for SPI in PCI1xxxx Thangaraj Samynathan
2023-12-15 11:47 ` [PATCH SPI for-next 1/3] spi: mchp-pci1xxxx: Add support for DMA in SPI Thangaraj Samynathan
2023-12-15 11:47 ` [PATCH SPI for-next 2/3] spi: mchp-pci1xxxx: DMA Read support for copying data into SPI Buf Thangaraj Samynathan
@ 2023-12-15 11:47 ` Thangaraj Samynathan
2 siblings, 0 replies; 8+ messages in thread
From: Thangaraj Samynathan @ 2023-12-15 11:47 UTC (permalink / raw)
To: broonie
Cc: linux-spi, linux-kernel, Tharunkumar.Pasumarthi,
Kumaravel.Thiagarajan, Arun.Ramadoss, Ronnie.Kunin,
jegadheesan.gopalmanoharan
DMA Write setup is done in pci1xxxx_spi_transfer_with_dma, before
initiating the transaction. Once the SPI transaction complete interrupt
is received, doorbell is written to initiate DMA Write. DMA Write operation
copies the data from SPI RX buffer to CPU buffer.
Signed-off-by: Thangaraj Samynathan <thangaraj.s@microchip.com>
---
drivers/spi/spi-pci1xxxx.c | 93 +++++++++++++++++++++++++++++++++++---
1 file changed, 86 insertions(+), 7 deletions(-)
diff --git a/drivers/spi/spi-pci1xxxx.c b/drivers/spi/spi-pci1xxxx.c
index 824885ada9b6..5dcb63c367b9 100644
--- a/drivers/spi/spi-pci1xxxx.c
+++ b/drivers/spi/spi-pci1xxxx.c
@@ -57,8 +57,13 @@
/* DMA Related Registers */
#define SPI_DMA_ADDR_BASE (0x1000)
#define SPI_DMA_GLOBAL_WR_ENGINE_EN (SPI_DMA_ADDR_BASE + 0x0C)
+#define SPI_DMA_WR_DOORBELL_REG (SPI_DMA_ADDR_BASE + 0x10)
#define SPI_DMA_GLOBAL_RD_ENGINE_EN (SPI_DMA_ADDR_BASE + 0x2C)
#define SPI_DMA_RD_DOORBELL_REG (SPI_DMA_ADDR_BASE + 0x30)
+#define SPI_DMA_INTR_WR_STS (SPI_DMA_ADDR_BASE + 0x4C)
+#define SPI_DMA_WR_INT_MASK (SPI_DMA_ADDR_BASE + 0x54)
+#define SPI_DMA_INTR_WR_CLR (SPI_DMA_ADDR_BASE + 0x58)
+#define SPI_DMA_ERR_WR_STS (SPI_DMA_ADDR_BASE + 0x5C)
#define SPI_DMA_INTR_IMWR_WDONE_LOW (SPI_DMA_ADDR_BASE + 0x60)
#define SPI_DMA_INTR_IMWR_WDONE_HIGH (SPI_DMA_ADDR_BASE + 0x64)
#define SPI_DMA_INTR_IMWR_WABORT_LOW (SPI_DMA_ADDR_BASE + 0x68)
@@ -74,7 +79,9 @@
#define SPI_DMA_INTR_IMWR_RABORT_HIGH (SPI_DMA_ADDR_BASE + 0xD8)
#define SPI_DMA_INTR_RD_IMWR_DATA (SPI_DMA_ADDR_BASE + 0xDC)
+#define SPI_DMA_CH0_WR_BASE (SPI_DMA_ADDR_BASE + 0x200)
#define SPI_DMA_CH0_RD_BASE (SPI_DMA_ADDR_BASE + 0x300)
+#define SPI_DMA_CH1_WR_BASE (SPI_DMA_ADDR_BASE + 0x400)
#define SPI_DMA_CH1_RD_BASE (SPI_DMA_ADDR_BASE + 0x500)
#define SPI_DMA_CH_CTL1_OFFSET (0x00)
@@ -126,7 +133,9 @@
struct pci1xxxx_spi_internal {
u8 hw_inst;
bool spi_xfer_in_progress;
+ void *rx_buf;
bool dma_aborted_rd;
+ bool dma_aborted_wr;
int irq;
struct completion spi_xfer_done;
struct spi_controller *spi_host;
@@ -333,6 +342,26 @@ static void pci1xxxx_spi_setup_dma_read(struct pci1xxxx_spi_internal *p,
base + SPI_DMA_CH_DAR_HI_OFFSET);
}
+static void pci1xxxx_spi_setup_dma_write(struct pci1xxxx_spi_internal *p,
+ dma_addr_t dma_addr, u32 len)
+{
+ void *base;
+
+ if (!p->hw_inst)
+ base = p->parent->dma_offset_bar + SPI_DMA_CH0_WR_BASE;
+ else
+ base = p->parent->dma_offset_bar + SPI_DMA_CH1_WR_BASE;
+
+ writel(DMA_INTR_EN, base + SPI_DMA_CH_CTL1_OFFSET);
+ writel(len, base + SPI_DMA_CH_XFER_LEN_OFFSET);
+ writel(lower_32_bits(dma_addr), base + SPI_DMA_CH_DAR_LO_OFFSET);
+ writel(upper_32_bits(dma_addr), base + SPI_DMA_CH_DAR_HI_OFFSET);
+ writel(lower_32_bits(SPI_PERI_ADDR_BASE + SPI_MST_RSP_BUF_OFFSET(p->hw_inst)),
+ base + SPI_DMA_CH_SAR_LO_OFFSET);
+ writel(upper_32_bits(SPI_PERI_ADDR_BASE + SPI_MST_RSP_BUF_OFFSET(p->hw_inst)),
+ base + SPI_DMA_CH_SAR_HI_OFFSET);
+}
+
static void pci1xxxx_spi_setup(struct pci1xxxx_spi *par, u8 hw_inst, u32 mode,
u8 clkdiv, u32 len)
{
@@ -427,9 +456,9 @@ static int pci1xxxx_spi_transfer_with_dma(struct spi_controller *spi_ctlr,
struct pci1xxxx_spi_internal *p = spi_controller_get_devdata(spi_ctlr);
struct pci1xxxx_spi *par = p->parent;
struct device *dev = &par->dev->dev;
+ dma_addr_t rx_dma_addr = 0;
dma_addr_t tx_dma_addr = 0;
u64 bytes_transfered = 0;
- u64 bytes_recvd = 0;
int loop_count;
int ret = 0;
u32 regval;
@@ -439,6 +468,7 @@ static int pci1xxxx_spi_transfer_with_dma(struct spi_controller *spi_ctlr,
u32 i;
p->spi_xfer_in_progress = true;
+ p->rx_buf = xfer->rx_buf;
clkdiv = pci1xxxx_get_clock_div(xfer->speed_hz);
rx_buf = xfer->rx_buf;
regval = readl(par->reg_base + SPI_MST_EVENT_REG_OFFSET(p->hw_inst));
@@ -456,6 +486,15 @@ static int pci1xxxx_spi_transfer_with_dma(struct spi_controller *spi_ctlr,
goto error;
}
+ if (xfer->rx_buf) {
+ rx_dma_addr = dma_map_single(dev, (void *)xfer->rx_buf, xfer->len, DMA_FROM_DEVICE);
+ if (dma_mapping_error(NULL, rx_dma_addr)) {
+ rx_dma_addr = 0;
+ ret = -ENOMEM;
+ goto error;
+ }
+ }
+
loop_count = DIV_ROUND_UP(xfer->len, SPI_MAX_DATA_LEN);
len = SPI_MAX_DATA_LEN;
pci1xxxx_spi_setup(par, p->hw_inst, spi->mode, clkdiv, len);
@@ -466,6 +505,8 @@ static int pci1xxxx_spi_transfer_with_dma(struct spi_controller *spi_ctlr,
}
pci1xxxx_spi_setup_dma_read(p, (tx_dma_addr + bytes_transfered), len);
+ if (rx_dma_addr)
+ pci1xxxx_spi_setup_dma_write(p, (rx_dma_addr + bytes_transfered), len);
writel(p->hw_inst, par->dma_offset_bar + SPI_DMA_RD_DOORBELL_REG);
@@ -495,14 +536,31 @@ static int pci1xxxx_spi_transfer_with_dma(struct spi_controller *spi_ctlr,
p->dma_aborted_rd = false;
ret = -ECANCELED;
}
+ if (p->dma_aborted_wr) {
+ writel(SPI_DMA_ENGINE_DIS,
+ par->dma_offset_bar + SPI_DMA_GLOBAL_WR_ENGINE_EN);
+
+ /*
+ * DMA ENGINE reset takes time if any TLP
+ * completeion in progress, should wait
+ * till DMA Engine reset is completed.
+ */
+ ret = readl_poll_timeout(par->dma_offset_bar +
+ SPI_DMA_GLOBAL_WR_ENGINE_EN, regval,
+ (regval == 0x0), 0, USEC_PER_MSEC);
+ if (ret) {
+ ret = -ECANCELED;
+ goto error;
+ }
+
+ writel(SPI_DMA_ENGINE_EN,
+ par->dma_offset_bar + SPI_DMA_GLOBAL_WR_ENGINE_EN);
+ p->dma_aborted_wr = false;
+ ret = -ECANCELED;
+ }
goto error;
}
bytes_transfered += len;
- if (rx_buf) {
- memcpy_fromio(&rx_buf[bytes_recvd], par->reg_base +
- SPI_MST_RSP_BUF_OFFSET(p->hw_inst), len);
- bytes_recvd += len;
- }
ret = 0;
}
@@ -510,6 +568,8 @@ static int pci1xxxx_spi_transfer_with_dma(struct spi_controller *spi_ctlr,
p->spi_xfer_in_progress = false;
if (tx_dma_addr)
dma_unmap_single(dev, tx_dma_addr, xfer->len, DMA_TO_DEVICE);
+ if (rx_dma_addr)
+ dma_unmap_single(dev, rx_dma_addr, xfer->len, DMA_FROM_DEVICE);
return ret;
}
@@ -525,7 +585,11 @@ static irqreturn_t pci1xxxx_spi_isr(int irq, void *dev)
regval = readl(p->parent->reg_base + SPI_MST_EVENT_REG_OFFSET(p->hw_inst));
if (regval & SPI_INTR) {
/* Clear xfer_done */
- complete(&p->spi_xfer_done);
+ if (p->parent->can_dma && p->rx_buf)
+ writel(p->hw_inst, p->parent->dma_offset_bar +
+ SPI_DMA_WR_DOORBELL_REG);
+ else
+ complete(&p->parent->spi_int[p->hw_inst]->spi_xfer_done);
spi_int_fired = IRQ_HANDLED;
}
@@ -549,6 +613,21 @@ static irqreturn_t pci1xxxx_spi_isr(int irq, void *dev)
spi_int_fired = IRQ_HANDLED;
}
writel(regval, p->parent->dma_offset_bar + SPI_DMA_INTR_RD_CLR);
+
+ /* Clear the DMA WR INT */
+ regval = readl(p->parent->dma_offset_bar + SPI_DMA_INTR_WR_STS);
+ if (regval & SPI_DMA_DONE_INT_MASK) {
+ if (regval & SPI_DMA_CH0_DONE_INT)
+ complete(&p->parent->spi_int[SPI0]->spi_xfer_done);
+ if (regval & SPI_DMA_CH1_DONE_INT)
+ complete(&p->parent->spi_int[SPI1]->spi_xfer_done);
+ spi_int_fired = IRQ_HANDLED;
+ }
+ if (regval & SPI_DMA_ABORT_INT_MASK) {
+ p->dma_aborted_wr = true;
+ spi_int_fired = IRQ_HANDLED;
+ }
+ writel(regval, p->parent->dma_offset_bar + SPI_DMA_INTR_WR_CLR);
spin_unlock_irqrestore(&p->parent->dma_reg_lock, flags);
return spi_int_fired;
--
2.25.1
^ permalink raw reply related [flat|nested] 8+ messages in thread
* Re: [PATCH SPI for-next 2/3] spi: mchp-pci1xxxx: DMA Read support for copying data into SPI Buf
2023-12-15 11:47 ` [PATCH SPI for-next 2/3] spi: mchp-pci1xxxx: DMA Read support for copying data into SPI Buf Thangaraj Samynathan
@ 2023-12-15 13:29 ` Mark Brown
2023-12-20 6:55 ` Thangaraj.S
2023-12-16 1:17 ` kernel test robot
2023-12-16 10:44 ` kernel test robot
2 siblings, 1 reply; 8+ messages in thread
From: Mark Brown @ 2023-12-15 13:29 UTC (permalink / raw)
To: Thangaraj Samynathan
Cc: linux-spi, linux-kernel, Tharunkumar.Pasumarthi,
Kumaravel.Thiagarajan, Arun.Ramadoss, Ronnie.Kunin,
jegadheesan.gopalmanoharan
[-- Attachment #1: Type: text/plain, Size: 566 bytes --]
On Fri, Dec 15, 2023 at 05:17:47PM +0530, Thangaraj Samynathan wrote:
> + tx_dma_addr = dma_map_single(dev, (void *)xfer->tx_buf, xfer->len, DMA_TO_DEVICE);
> + if (dma_mapping_error(NULL, tx_dma_addr)) {
> + tx_dma_addr = 0;
> + ret = -ENOMEM;
> + goto error;
> + }
The core can do all the DMA mapping for you if you provide a can_dma()
operation, this supports switching between DMA and non-DMA modes per
transfer - often you'll get better performance from PIO for smaller
lengths due to the overhead of setting up DMA and taking the interrupt
on completion.
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH SPI for-next 2/3] spi: mchp-pci1xxxx: DMA Read support for copying data into SPI Buf
2023-12-15 11:47 ` [PATCH SPI for-next 2/3] spi: mchp-pci1xxxx: DMA Read support for copying data into SPI Buf Thangaraj Samynathan
2023-12-15 13:29 ` Mark Brown
@ 2023-12-16 1:17 ` kernel test robot
2023-12-16 10:44 ` kernel test robot
2 siblings, 0 replies; 8+ messages in thread
From: kernel test robot @ 2023-12-16 1:17 UTC (permalink / raw)
To: Thangaraj Samynathan, broonie
Cc: oe-kbuild-all, linux-spi, linux-kernel, Tharunkumar.Pasumarthi,
Kumaravel.Thiagarajan, Arun.Ramadoss, Ronnie.Kunin,
jegadheesan.gopalmanoharan
Hi Thangaraj,
kernel test robot noticed the following build warnings:
[auto build test WARNING on broonie-spi/for-next]
[also build test WARNING on linus/master v6.7-rc5 next-20231215]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]
url: https://github.com/intel-lab-lkp/linux/commits/Thangaraj-Samynathan/spi-mchp-pci1xxxx-Add-support-for-DMA-in-SPI/20231215-195133
base: https://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi.git for-next
patch link: https://lore.kernel.org/r/20231215114748.152319-3-thangaraj.s%40microchip.com
patch subject: [PATCH SPI for-next 2/3] spi: mchp-pci1xxxx: DMA Read support for copying data into SPI Buf
config: loongarch-allmodconfig (https://download.01.org/0day-ci/archive/20231216/202312160922.Eb2xnL8g-lkp@intel.com/config)
compiler: loongarch64-linux-gcc (GCC) 13.2.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20231216/202312160922.Eb2xnL8g-lkp@intel.com/reproduce)
If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202312160922.Eb2xnL8g-lkp@intel.com/
All warnings (new ones prefixed by >>):
drivers/spi/spi-pci1xxxx.c: In function 'pci1xxxx_spi_transfer_one':
>> drivers/spi/spi-pci1xxxx.c:366:13: warning: variable 'mode' set but not used [-Wunused-but-set-variable]
366 | int mode, len, loop_iter, transfer_len;
| ^~~~
vim +/mode +366 drivers/spi/spi-pci1xxxx.c
bf37ce4603316bb Thangaraj Samynathan 2023-12-15 361
1cc0cbea7167af5 Tharun Kumar P 2022-10-06 362 static int pci1xxxx_spi_transfer_one(struct spi_controller *spi_ctlr,
1cc0cbea7167af5 Tharun Kumar P 2022-10-06 363 struct spi_device *spi, struct spi_transfer *xfer)
1cc0cbea7167af5 Tharun Kumar P 2022-10-06 364 {
1cc0cbea7167af5 Tharun Kumar P 2022-10-06 365 struct pci1xxxx_spi_internal *p = spi_controller_get_devdata(spi_ctlr);
1cc0cbea7167af5 Tharun Kumar P 2022-10-06 @366 int mode, len, loop_iter, transfer_len;
1cc0cbea7167af5 Tharun Kumar P 2022-10-06 367 struct pci1xxxx_spi *par = p->parent;
1cc0cbea7167af5 Tharun Kumar P 2022-10-06 368 unsigned long bytes_transfered;
1cc0cbea7167af5 Tharun Kumar P 2022-10-06 369 unsigned long bytes_recvd;
1cc0cbea7167af5 Tharun Kumar P 2022-10-06 370 unsigned long loop_count;
1cc0cbea7167af5 Tharun Kumar P 2022-10-06 371 u8 *rx_buf, result;
1cc0cbea7167af5 Tharun Kumar P 2022-10-06 372 const u8 *tx_buf;
1cc0cbea7167af5 Tharun Kumar P 2022-10-06 373 u32 regval;
1cc0cbea7167af5 Tharun Kumar P 2022-10-06 374 u8 clkdiv;
1cc0cbea7167af5 Tharun Kumar P 2022-10-06 375
1cc0cbea7167af5 Tharun Kumar P 2022-10-06 376 p->spi_xfer_in_progress = true;
1cc0cbea7167af5 Tharun Kumar P 2022-10-06 377 mode = spi->mode;
1cc0cbea7167af5 Tharun Kumar P 2022-10-06 378 clkdiv = pci1xxxx_get_clock_div(xfer->speed_hz);
1cc0cbea7167af5 Tharun Kumar P 2022-10-06 379 tx_buf = xfer->tx_buf;
1cc0cbea7167af5 Tharun Kumar P 2022-10-06 380 rx_buf = xfer->rx_buf;
1cc0cbea7167af5 Tharun Kumar P 2022-10-06 381 transfer_len = xfer->len;
1cc0cbea7167af5 Tharun Kumar P 2022-10-06 382 regval = readl(par->reg_base + SPI_MST_EVENT_REG_OFFSET(p->hw_inst));
1cc0cbea7167af5 Tharun Kumar P 2022-10-06 383 writel(regval, par->reg_base + SPI_MST_EVENT_REG_OFFSET(p->hw_inst));
1cc0cbea7167af5 Tharun Kumar P 2022-10-06 384
1cc0cbea7167af5 Tharun Kumar P 2022-10-06 385 if (tx_buf) {
1cc0cbea7167af5 Tharun Kumar P 2022-10-06 386 bytes_transfered = 0;
1cc0cbea7167af5 Tharun Kumar P 2022-10-06 387 bytes_recvd = 0;
1cc0cbea7167af5 Tharun Kumar P 2022-10-06 388 loop_count = transfer_len / SPI_MAX_DATA_LEN;
1cc0cbea7167af5 Tharun Kumar P 2022-10-06 389 if (transfer_len % SPI_MAX_DATA_LEN != 0)
1cc0cbea7167af5 Tharun Kumar P 2022-10-06 390 loop_count += 1;
1cc0cbea7167af5 Tharun Kumar P 2022-10-06 391
1cc0cbea7167af5 Tharun Kumar P 2022-10-06 392 for (loop_iter = 0; loop_iter < loop_count; loop_iter++) {
1cc0cbea7167af5 Tharun Kumar P 2022-10-06 393 len = SPI_MAX_DATA_LEN;
1cc0cbea7167af5 Tharun Kumar P 2022-10-06 394 if ((transfer_len % SPI_MAX_DATA_LEN != 0) &&
1cc0cbea7167af5 Tharun Kumar P 2022-10-06 395 (loop_iter == loop_count - 1))
1cc0cbea7167af5 Tharun Kumar P 2022-10-06 396 len = transfer_len % SPI_MAX_DATA_LEN;
1cc0cbea7167af5 Tharun Kumar P 2022-10-06 397
1cc0cbea7167af5 Tharun Kumar P 2022-10-06 398 reinit_completion(&p->spi_xfer_done);
1cc0cbea7167af5 Tharun Kumar P 2022-10-06 399 memcpy_toio(par->reg_base + SPI_MST_CMD_BUF_OFFSET(p->hw_inst),
1cc0cbea7167af5 Tharun Kumar P 2022-10-06 400 &tx_buf[bytes_transfered], len);
1cc0cbea7167af5 Tharun Kumar P 2022-10-06 401 bytes_transfered += len;
bf37ce4603316bb Thangaraj Samynathan 2023-12-15 402 pci1xxxx_spi_setup(par, p->hw_inst, spi->mode, clkdiv, len);
bf37ce4603316bb Thangaraj Samynathan 2023-12-15 403 pci1xxxx_start_spi_xfer(p, p->hw_inst);
1cc0cbea7167af5 Tharun Kumar P 2022-10-06 404
1cc0cbea7167af5 Tharun Kumar P 2022-10-06 405 /* Wait for DMA_TERM interrupt */
1cc0cbea7167af5 Tharun Kumar P 2022-10-06 406 result = wait_for_completion_timeout(&p->spi_xfer_done,
1cc0cbea7167af5 Tharun Kumar P 2022-10-06 407 PCI1XXXX_SPI_TIMEOUT);
1cc0cbea7167af5 Tharun Kumar P 2022-10-06 408 if (!result)
1cc0cbea7167af5 Tharun Kumar P 2022-10-06 409 return -ETIMEDOUT;
1cc0cbea7167af5 Tharun Kumar P 2022-10-06 410
1cc0cbea7167af5 Tharun Kumar P 2022-10-06 411 if (rx_buf) {
1cc0cbea7167af5 Tharun Kumar P 2022-10-06 412 memcpy_fromio(&rx_buf[bytes_recvd], par->reg_base +
1cc0cbea7167af5 Tharun Kumar P 2022-10-06 413 SPI_MST_RSP_BUF_OFFSET(p->hw_inst), len);
1cc0cbea7167af5 Tharun Kumar P 2022-10-06 414 bytes_recvd += len;
1cc0cbea7167af5 Tharun Kumar P 2022-10-06 415 }
1cc0cbea7167af5 Tharun Kumar P 2022-10-06 416 }
1cc0cbea7167af5 Tharun Kumar P 2022-10-06 417 }
1cc0cbea7167af5 Tharun Kumar P 2022-10-06 418 p->spi_xfer_in_progress = false;
1cc0cbea7167af5 Tharun Kumar P 2022-10-06 419
1cc0cbea7167af5 Tharun Kumar P 2022-10-06 420 return 0;
1cc0cbea7167af5 Tharun Kumar P 2022-10-06 421 }
1cc0cbea7167af5 Tharun Kumar P 2022-10-06 422
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH SPI for-next 2/3] spi: mchp-pci1xxxx: DMA Read support for copying data into SPI Buf
2023-12-15 11:47 ` [PATCH SPI for-next 2/3] spi: mchp-pci1xxxx: DMA Read support for copying data into SPI Buf Thangaraj Samynathan
2023-12-15 13:29 ` Mark Brown
2023-12-16 1:17 ` kernel test robot
@ 2023-12-16 10:44 ` kernel test robot
2 siblings, 0 replies; 8+ messages in thread
From: kernel test robot @ 2023-12-16 10:44 UTC (permalink / raw)
To: Thangaraj Samynathan, broonie
Cc: oe-kbuild-all, linux-spi, linux-kernel, Tharunkumar.Pasumarthi,
Kumaravel.Thiagarajan, Arun.Ramadoss, Ronnie.Kunin,
jegadheesan.gopalmanoharan
Hi Thangaraj,
kernel test robot noticed the following build warnings:
[auto build test WARNING on broonie-spi/for-next]
[also build test WARNING on linus/master v6.7-rc5 next-20231215]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]
url: https://github.com/intel-lab-lkp/linux/commits/Thangaraj-Samynathan/spi-mchp-pci1xxxx-Add-support-for-DMA-in-SPI/20231215-195133
base: https://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi.git for-next
patch link: https://lore.kernel.org/r/20231215114748.152319-3-thangaraj.s%40microchip.com
patch subject: [PATCH SPI for-next 2/3] spi: mchp-pci1xxxx: DMA Read support for copying data into SPI Buf
config: arc-randconfig-r132-20231216 (https://download.01.org/0day-ci/archive/20231216/202312161832.s8L4PtmO-lkp@intel.com/config)
compiler: arceb-elf-gcc (GCC) 13.2.0
reproduce: (https://download.01.org/0day-ci/archive/20231216/202312161832.s8L4PtmO-lkp@intel.com/reproduce)
If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202312161832.s8L4PtmO-lkp@intel.com/
sparse warnings: (new ones prefixed by >>)
>> drivers/spi/spi-pci1xxxx.c:321:22: sparse: sparse: incorrect type in assignment (different address spaces) @@ expected void *base @@ got void [noderef] __iomem * @@
drivers/spi/spi-pci1xxxx.c:321:22: sparse: expected void *base
drivers/spi/spi-pci1xxxx.c:321:22: sparse: got void [noderef] __iomem *
drivers/spi/spi-pci1xxxx.c:323:22: sparse: sparse: incorrect type in assignment (different address spaces) @@ expected void *base @@ got void [noderef] __iomem * @@
drivers/spi/spi-pci1xxxx.c:323:22: sparse: expected void *base
drivers/spi/spi-pci1xxxx.c:323:22: sparse: got void [noderef] __iomem *
>> drivers/spi/spi-pci1xxxx.c:325:9: sparse: sparse: incorrect type in argument 2 (different address spaces) @@ expected void volatile [noderef] __iomem *addr @@ got void * @@
drivers/spi/spi-pci1xxxx.c:325:9: sparse: expected void volatile [noderef] __iomem *addr
drivers/spi/spi-pci1xxxx.c:325:9: sparse: got void *
drivers/spi/spi-pci1xxxx.c:326:9: sparse: sparse: incorrect type in argument 2 (different address spaces) @@ expected void volatile [noderef] __iomem *addr @@ got void * @@
drivers/spi/spi-pci1xxxx.c:326:9: sparse: expected void volatile [noderef] __iomem *addr
drivers/spi/spi-pci1xxxx.c:326:9: sparse: got void *
drivers/spi/spi-pci1xxxx.c:327:9: sparse: sparse: incorrect type in argument 2 (different address spaces) @@ expected void volatile [noderef] __iomem *addr @@ got void * @@
drivers/spi/spi-pci1xxxx.c:327:9: sparse: expected void volatile [noderef] __iomem *addr
drivers/spi/spi-pci1xxxx.c:327:9: sparse: got void *
drivers/spi/spi-pci1xxxx.c:328:9: sparse: sparse: incorrect type in argument 2 (different address spaces) @@ expected void volatile [noderef] __iomem *addr @@ got void * @@
drivers/spi/spi-pci1xxxx.c:328:9: sparse: expected void volatile [noderef] __iomem *addr
drivers/spi/spi-pci1xxxx.c:328:9: sparse: got void *
drivers/spi/spi-pci1xxxx.c:330:9: sparse: sparse: incorrect type in argument 2 (different address spaces) @@ expected void volatile [noderef] __iomem *addr @@ got void * @@
drivers/spi/spi-pci1xxxx.c:330:9: sparse: expected void volatile [noderef] __iomem *addr
drivers/spi/spi-pci1xxxx.c:330:9: sparse: got void *
drivers/spi/spi-pci1xxxx.c:332:9: sparse: sparse: incorrect type in argument 2 (different address spaces) @@ expected void volatile [noderef] __iomem *addr @@ got void * @@
drivers/spi/spi-pci1xxxx.c:332:9: sparse: expected void volatile [noderef] __iomem *addr
drivers/spi/spi-pci1xxxx.c:332:9: sparse: got void *
drivers/spi/spi-pci1xxxx.c: note: in included file (through include/linux/mmzone.h, include/linux/gfp.h, include/linux/xarray.h, ...):
include/linux/page-flags.h:242:46: sparse: sparse: self-comparison always evaluates to false
vim +321 drivers/spi/spi-pci1xxxx.c
314
315 static void pci1xxxx_spi_setup_dma_read(struct pci1xxxx_spi_internal *p,
316 dma_addr_t dma_addr, u32 len)
317 {
318 void *base;
319
320 if (!p->hw_inst)
> 321 base = p->parent->dma_offset_bar + SPI_DMA_CH0_RD_BASE;
322 else
323 base = p->parent->dma_offset_bar + SPI_DMA_CH1_RD_BASE;
324
> 325 writel(DMA_INTR_EN, base + SPI_DMA_CH_CTL1_OFFSET);
326 writel(len, base + SPI_DMA_CH_XFER_LEN_OFFSET);
327 writel(lower_32_bits(dma_addr), base + SPI_DMA_CH_SAR_LO_OFFSET);
328 writel(upper_32_bits(dma_addr), base + SPI_DMA_CH_SAR_HI_OFFSET);
329 /* Updated SPI Command Registers */
330 writel(lower_32_bits(SPI_PERI_ADDR_BASE + SPI_MST_CMD_BUF_OFFSET(p->hw_inst)),
331 base + SPI_DMA_CH_DAR_LO_OFFSET);
332 writel(upper_32_bits(SPI_PERI_ADDR_BASE + SPI_MST_CMD_BUF_OFFSET(p->hw_inst)),
333 base + SPI_DMA_CH_DAR_HI_OFFSET);
334 }
335
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH SPI for-next 2/3] spi: mchp-pci1xxxx: DMA Read support for copying data into SPI Buf
2023-12-15 13:29 ` Mark Brown
@ 2023-12-20 6:55 ` Thangaraj.S
0 siblings, 0 replies; 8+ messages in thread
From: Thangaraj.S @ 2023-12-20 6:55 UTC (permalink / raw)
To: broonie
Cc: linux-spi, Arun.Ramadoss, Jegadheesan.GopalManoharan,
linux-kernel, Kumaravel.Thiagarajan, Tharunkumar.Pasumarthi,
Ronnie.Kunin
Hi Mark,
Thanks for your comments. Will send the updated patch shortly.
On Fri, 2023-12-15 at 13:29 +0000, Mark Brown wrote:
> EXTERNAL EMAIL: Do not click links or open attachments unless you
> know the content is safe
^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2023-12-20 6:55 UTC | newest]
Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-12-15 11:47 [PATCH SPI for-next 0/3] DMA Support for SPI in PCI1xxxx Thangaraj Samynathan
2023-12-15 11:47 ` [PATCH SPI for-next 1/3] spi: mchp-pci1xxxx: Add support for DMA in SPI Thangaraj Samynathan
2023-12-15 11:47 ` [PATCH SPI for-next 2/3] spi: mchp-pci1xxxx: DMA Read support for copying data into SPI Buf Thangaraj Samynathan
2023-12-15 13:29 ` Mark Brown
2023-12-20 6:55 ` Thangaraj.S
2023-12-16 1:17 ` kernel test robot
2023-12-16 10:44 ` kernel test robot
2023-12-15 11:47 ` [PATCH SPI for-next 3/3] spi: mchp-pci1xxxx: DMA Write Support for copying data from " Thangaraj Samynathan
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).