Skip to content

Commit 08ba930

Browse files
committed
Merge series "spi: dw: Add generic DW DMA controller support" from Serge Semin <[email protected]>:
Baikal-T1 SoC provides a DW DMA controller to perform low-speed peripherals Mem-to-Dev and Dev-to-Mem transaction. This is also applicable to the DW APB SSI devices embedded into the SoC. Currently the DMA-based transfers are supported by the DW APB SPI driver only as a middle layer code for Intel MID/Elkhart PCI devices. Seeing the same code can be used for normal platform DMAC device we introduced a set of patches to fix it within this series. First of all we need to add the Tx and Rx DMA channels support into the DW APB SSI binding. Then there are several fixes and cleanups provided as a initial preparation for the Generic DMA support integration: add Tx/Rx finish wait methods, clear DMAC register when done or stopped, Fix native CS being unset, enable interrupts in accordance with DMA xfer mode, discard static DW DMA slave structures, discard unused void priv pointer and dma_width member of the dw_spi structure, provide the DMA Tx/Rx burst length parametrisation and make sure it's optionally set in accordance with the DMA max-burst capability. In order to have the DW APB SSI MMIO driver working with DMA we need to initialize the paddr field with the physical base address of the DW APB SSI registers space. Then we unpin the Intel MID specific code from the generic DMA one and placed it into the spi-dw-pci.c driver, which is a better place for it anyway. After that the naming cleanups are performed since the code is going to be used for a generic DMAC device. Finally the Generic DMA initialization can be added to the generic version of the DW APB SSI IP. Last but not least we traditionally convert the legacy plain text-based dt-binding file with yaml-based one and as a cherry on a cake replace the manually written DebugFS registers read method with a ready-to-use for the same purpose regset32 DebugFS interface usage. This patchset is rebased and tested on the spi/for-next (5.7-rc5): base-commit: fe9fce6 ("Merge remote-tracking branch 'spi/for-5.8' into spi-next") Link: https://lore.kernel.org/linux-spi/[email protected]/ Changelog v2: - Rebase on top of the spi repository for-next branch. - Move bindings conversion patch to the tail of the series. - Move fixes to the head of the series. - Apply as many changes as possible to be applied the Generic DMA functionality support is added and the spi-dw-mid is moved to the spi-dw-dma driver. - Discard patch "spi: dw: Fix dma_slave_config used partly uninitialized" since the problem has already been fixed. - Add new patch "spi: dw: Discard unused void priv pointer". - Add new patch "spi: dw: Discard dma_width member of the dw_spi structure". n_bytes member of the DW SPI data can be used instead. - Build the DMA functionality into the DW APB SSI core if required instead of creating a separate kernel module. - Use conditional statement instead of the ternary operator in the ref clock getter. Link: https://lore.kernel.org/linux-spi/[email protected]/ Changelog v3: - Use spi_delay_exec() method to wait for the DMA operation completion. - Explicitly initialize the dw_dma_slave members on stack. - Discard the dws->fifo_len utilization in the Tx FIFO DMA threshold setting from the patch where we just add the default burst length constants. - Use min() method to calculate the optimal burst values. - Add new patch which moves the spi-dw.c source file to spi-dw-core.c in order to preserve the DW APB SSI core driver name. - Add commas in the debugfs_reg32 structure initializer and after the last entry of the dw_spi_dbgfs_regs array. Link: https://lore.kernel.org/linux-spi/[email protected] Changelog v4: - Get back ndelay() method to wait for an SPI transfer completion. spi_delay_exec() isn't suitable for the atomic context. Link: https://lore.kernel.org/linux-spi/[email protected] Changelog v5: - Refactor the Tx/Rx DMA-based SPI transfers wait methods. - Add a new patch "spi: dw: Set xfer effective_speed_hz". - Add a new patch "spi: dw: Return any value retrieved from the dma_transfer callback" as a preparation patch before implementing the local DMA, Tx SPI and Rx SPI transfers wait methods. - Add a new patch "spi: dw: Locally wait for the DMA transactions completion", which provides a local DMA transaction complete method - Create a dedicated patch which adds the Rx-done wait method: "spi: dw: Add SPI Rx-done wait method to DMA-based transfer". - Add more detailed description of the problems the Tx/Rx-wait methods-related patches fix. - Wait for the SPI Tx and Rx transfers being finished in the mid_spi_dma_transfer() method executed in the task context. - Use spi_delay_exec() to wait for the SPI Tx/Rx completion, since now the driver calls the wait methods in the kernel thread context. - Use SPI_DELAY_UNIT_SCK spi_delay unit for Tx-wait delay, since SPI xfer's are now have the effective_speed_hz initialized. - Rx-wait for a delay correlated with the APB/SSI synchronous clock rate instead of using the SPI bus clock rate. Link: https://lore.kernel.org/linux-spi/[email protected] Changelog v6: - Provide a more detailed description of the patch: 2901db35bea1 ("spi: dw: Locally wait for the DMA transfers completion") - Calculate the Rx delay with better accuracy by moving 4-multiplication to the head of the formulae: ns = 4U * NSEC_PER_SEC / dws->max_freq * nents. Co-developed-by: Georgy Vlasov <[email protected]> Signed-off-by: Georgy Vlasov <[email protected]> Co-developed-by: Ramil Zaripov <[email protected]> Signed-off-by: Ramil Zaripov <[email protected]> Signed-off-by: Serge Semin <[email protected]> Cc: Alexey Malahov <[email protected]> Cc: Maxim Kaurkin <[email protected]> Cc: Pavel Parkhomenko <[email protected]> Cc: Ekaterina Skachko <[email protected]> Cc: Vadim Vlasov <[email protected]> Cc: Alexey Kolotnikov <[email protected]> Cc: Thomas Bogendoerfer <[email protected]> Cc: Arnd Bergmann <[email protected]> Cc: Andy Shevchenko <[email protected]> Cc: Feng Tang <[email protected]> Cc: Rob Herring <[email protected]> Cc: [email protected] Cc: [email protected] Cc: [email protected] Cc: [email protected] Serge Semin (16): spi: dw: Set xfer effective_speed_hz spi: dw: Return any value retrieved from the dma_transfer callback spi: dw: Locally wait for the DMA transfers completion spi: dw: Add SPI Tx-done wait method to DMA-based transfer spi: dw: Add SPI Rx-done wait method to DMA-based transfer spi: dw: Parameterize the DMA Rx/Tx burst length spi: dw: Use DMA max burst to set the request thresholds spi: dw: Fix Rx-only DMA transfers spi: dw: Add core suffix to the DW APB SSI core source file spi: dw: Move Non-DMA code to the DW PCIe-SPI driver spi: dw: Remove DW DMA code dependency from DW_DMAC_PCI spi: dw: Add DW SPI DMA/PCI/MMIO dependency on the DW SPI core spi: dw: Cleanup generic DW DMA code namings spi: dw: Add DMA support to the DW SPI MMIO driver spi: dw: Use regset32 DebugFS method to create regdump file dt-bindings: spi: Convert DW SPI binding to DT schema .../bindings/spi/snps,dw-apb-ssi.txt | 44 -- .../bindings/spi/snps,dw-apb-ssi.yaml | 127 +++++ .../devicetree/bindings/spi/spi-dw.txt | 24 - drivers/spi/Kconfig | 15 +- drivers/spi/Makefile | 5 +- drivers/spi/{spi-dw.c => spi-dw-core.c} | 95 ++-- drivers/spi/spi-dw-dma.c | 482 ++++++++++++++++++ drivers/spi/spi-dw-mid.c | 382 -------------- drivers/spi/spi-dw-mmio.c | 4 + drivers/spi/spi-dw-pci.c | 50 +- drivers/spi/spi-dw.h | 20 +- 11 files changed, 719 insertions(+), 529 deletions(-) delete mode 100644 Documentation/devicetree/bindings/spi/snps,dw-apb-ssi.txt create mode 100644 Documentation/devicetree/bindings/spi/snps,dw-apb-ssi.yaml delete mode 100644 Documentation/devicetree/bindings/spi/spi-dw.txt rename drivers/spi/{spi-dw.c => spi-dw-core.c} (82%) create mode 100644 drivers/spi/spi-dw-dma.c delete mode 100644 drivers/spi/spi-dw-mid.c -- 2.26.2
2 parents 2604d48 + 8378449 commit 08ba930

File tree

8 files changed

+592
-461
lines changed

8 files changed

+592
-461
lines changed

drivers/spi/Kconfig

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -226,17 +226,20 @@ config SPI_DESIGNWARE
226226
help
227227
general driver for SPI controller core from DesignWare
228228

229+
if SPI_DESIGNWARE
230+
231+
config SPI_DW_DMA
232+
bool "DMA support for DW SPI controller"
233+
229234
config SPI_DW_PCI
230235
tristate "PCI interface driver for DW SPI core"
231-
depends on SPI_DESIGNWARE && PCI
232-
233-
config SPI_DW_MID_DMA
234-
bool "DMA support for DW SPI controller on Intel MID platform"
235-
depends on SPI_DW_PCI && DW_DMAC_PCI
236+
depends on PCI
236237

237238
config SPI_DW_MMIO
238239
tristate "Memory-mapped io interface driver for DW SPI core"
239-
depends on SPI_DESIGNWARE
240+
depends on HAS_IOMEM
241+
242+
endif
240243

241244
config SPI_DLN2
242245
tristate "Diolan DLN-2 USB SPI adapter"

drivers/spi/Makefile

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,9 +36,10 @@ obj-$(CONFIG_SPI_COLDFIRE_QSPI) += spi-coldfire-qspi.o
3636
obj-$(CONFIG_SPI_DAVINCI) += spi-davinci.o
3737
obj-$(CONFIG_SPI_DLN2) += spi-dln2.o
3838
obj-$(CONFIG_SPI_DESIGNWARE) += spi-dw.o
39+
spi-dw-y := spi-dw-core.o
40+
spi-dw-$(CONFIG_SPI_DW_DMA) += spi-dw-dma.o
3941
obj-$(CONFIG_SPI_DW_MMIO) += spi-dw-mmio.o
40-
obj-$(CONFIG_SPI_DW_PCI) += spi-dw-midpci.o
41-
spi-dw-midpci-objs := spi-dw-pci.o spi-dw-mid.o
42+
obj-$(CONFIG_SPI_DW_PCI) += spi-dw-pci.o
4243
obj-$(CONFIG_SPI_EFM32) += spi-efm32.o
4344
obj-$(CONFIG_SPI_EP93XX) += spi-ep93xx.o
4445
obj-$(CONFIG_SPI_FALCON) += spi-falcon.o

drivers/spi/spi-dw.c renamed to drivers/spi/spi-dw-core.c

Lines changed: 30 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -29,66 +29,29 @@ struct chip_data {
2929
};
3030

3131
#ifdef CONFIG_DEBUG_FS
32-
#define SPI_REGS_BUFSIZE 1024
33-
static ssize_t dw_spi_show_regs(struct file *file, char __user *user_buf,
34-
size_t count, loff_t *ppos)
35-
{
36-
struct dw_spi *dws = file->private_data;
37-
char *buf;
38-
u32 len = 0;
39-
ssize_t ret;
40-
41-
buf = kzalloc(SPI_REGS_BUFSIZE, GFP_KERNEL);
42-
if (!buf)
43-
return 0;
44-
45-
len += scnprintf(buf + len, SPI_REGS_BUFSIZE - len,
46-
"%s registers:\n", dev_name(&dws->master->dev));
47-
len += scnprintf(buf + len, SPI_REGS_BUFSIZE - len,
48-
"=================================\n");
49-
len += scnprintf(buf + len, SPI_REGS_BUFSIZE - len,
50-
"CTRLR0: \t0x%08x\n", dw_readl(dws, DW_SPI_CTRLR0));
51-
len += scnprintf(buf + len, SPI_REGS_BUFSIZE - len,
52-
"CTRLR1: \t0x%08x\n", dw_readl(dws, DW_SPI_CTRLR1));
53-
len += scnprintf(buf + len, SPI_REGS_BUFSIZE - len,
54-
"SSIENR: \t0x%08x\n", dw_readl(dws, DW_SPI_SSIENR));
55-
len += scnprintf(buf + len, SPI_REGS_BUFSIZE - len,
56-
"SER: \t\t0x%08x\n", dw_readl(dws, DW_SPI_SER));
57-
len += scnprintf(buf + len, SPI_REGS_BUFSIZE - len,
58-
"BAUDR: \t\t0x%08x\n", dw_readl(dws, DW_SPI_BAUDR));
59-
len += scnprintf(buf + len, SPI_REGS_BUFSIZE - len,
60-
"TXFTLR: \t0x%08x\n", dw_readl(dws, DW_SPI_TXFTLR));
61-
len += scnprintf(buf + len, SPI_REGS_BUFSIZE - len,
62-
"RXFTLR: \t0x%08x\n", dw_readl(dws, DW_SPI_RXFTLR));
63-
len += scnprintf(buf + len, SPI_REGS_BUFSIZE - len,
64-
"TXFLR: \t\t0x%08x\n", dw_readl(dws, DW_SPI_TXFLR));
65-
len += scnprintf(buf + len, SPI_REGS_BUFSIZE - len,
66-
"RXFLR: \t\t0x%08x\n", dw_readl(dws, DW_SPI_RXFLR));
67-
len += scnprintf(buf + len, SPI_REGS_BUFSIZE - len,
68-
"SR: \t\t0x%08x\n", dw_readl(dws, DW_SPI_SR));
69-
len += scnprintf(buf + len, SPI_REGS_BUFSIZE - len,
70-
"IMR: \t\t0x%08x\n", dw_readl(dws, DW_SPI_IMR));
71-
len += scnprintf(buf + len, SPI_REGS_BUFSIZE - len,
72-
"ISR: \t\t0x%08x\n", dw_readl(dws, DW_SPI_ISR));
73-
len += scnprintf(buf + len, SPI_REGS_BUFSIZE - len,
74-
"DMACR: \t\t0x%08x\n", dw_readl(dws, DW_SPI_DMACR));
75-
len += scnprintf(buf + len, SPI_REGS_BUFSIZE - len,
76-
"DMATDLR: \t0x%08x\n", dw_readl(dws, DW_SPI_DMATDLR));
77-
len += scnprintf(buf + len, SPI_REGS_BUFSIZE - len,
78-
"DMARDLR: \t0x%08x\n", dw_readl(dws, DW_SPI_DMARDLR));
79-
len += scnprintf(buf + len, SPI_REGS_BUFSIZE - len,
80-
"=================================\n");
81-
82-
ret = simple_read_from_buffer(user_buf, count, ppos, buf, len);
83-
kfree(buf);
84-
return ret;
32+
33+
#define DW_SPI_DBGFS_REG(_name, _off) \
34+
{ \
35+
.name = _name, \
36+
.offset = _off, \
8537
}
8638

87-
static const struct file_operations dw_spi_regs_ops = {
88-
.owner = THIS_MODULE,
89-
.open = simple_open,
90-
.read = dw_spi_show_regs,
91-
.llseek = default_llseek,
39+
static const struct debugfs_reg32 dw_spi_dbgfs_regs[] = {
40+
DW_SPI_DBGFS_REG("CTRLR0", DW_SPI_CTRLR0),
41+
DW_SPI_DBGFS_REG("CTRLR1", DW_SPI_CTRLR1),
42+
DW_SPI_DBGFS_REG("SSIENR", DW_SPI_SSIENR),
43+
DW_SPI_DBGFS_REG("SER", DW_SPI_SER),
44+
DW_SPI_DBGFS_REG("BAUDR", DW_SPI_BAUDR),
45+
DW_SPI_DBGFS_REG("TXFTLR", DW_SPI_TXFTLR),
46+
DW_SPI_DBGFS_REG("RXFTLR", DW_SPI_RXFTLR),
47+
DW_SPI_DBGFS_REG("TXFLR", DW_SPI_TXFLR),
48+
DW_SPI_DBGFS_REG("RXFLR", DW_SPI_RXFLR),
49+
DW_SPI_DBGFS_REG("SR", DW_SPI_SR),
50+
DW_SPI_DBGFS_REG("IMR", DW_SPI_IMR),
51+
DW_SPI_DBGFS_REG("ISR", DW_SPI_ISR),
52+
DW_SPI_DBGFS_REG("DMACR", DW_SPI_DMACR),
53+
DW_SPI_DBGFS_REG("DMATDLR", DW_SPI_DMATDLR),
54+
DW_SPI_DBGFS_REG("DMARDLR", DW_SPI_DMARDLR),
9255
};
9356

9457
static int dw_spi_debugfs_init(struct dw_spi *dws)
@@ -100,8 +63,11 @@ static int dw_spi_debugfs_init(struct dw_spi *dws)
10063
if (!dws->debugfs)
10164
return -ENOMEM;
10265

103-
debugfs_create_file("registers", S_IFREG | S_IRUGO,
104-
dws->debugfs, (void *)dws, &dw_spi_regs_ops);
66+
dws->regset.regs = dw_spi_dbgfs_regs;
67+
dws->regset.nregs = ARRAY_SIZE(dw_spi_dbgfs_regs);
68+
dws->regset.base = dws->regs;
69+
debugfs_create_regset32("registers", 0400, dws->debugfs, &dws->regset);
70+
10571
return 0;
10672
}
10773

@@ -352,6 +318,7 @@ static int dw_spi_transfer_one(struct spi_controller *master,
352318
spi_set_clk(dws, chip->clk_div);
353319
}
354320

321+
transfer->effective_speed_hz = dws->max_freq / chip->clk_div;
355322
dws->n_bytes = DIV_ROUND_UP(transfer->bits_per_word, BITS_PER_BYTE);
356323

357324
cr0 = dws->update_cr0(master, spi, transfer);
@@ -388,11 +355,8 @@ static int dw_spi_transfer_one(struct spi_controller *master,
388355

389356
spi_enable_chip(dws, 1);
390357

391-
if (dws->dma_mapped) {
392-
ret = dws->dma_ops->dma_transfer(dws, transfer);
393-
if (ret < 0)
394-
return ret;
395-
}
358+
if (dws->dma_mapped)
359+
return dws->dma_ops->dma_transfer(dws, transfer);
396360

397361
return 1;
398362
}
@@ -517,6 +481,7 @@ int dw_spi_add_host(struct device *dev, struct dw_spi *dws)
517481
dev_warn(dev, "DMA init failed\n");
518482
} else {
519483
master->can_dma = dws->dma_ops->can_dma;
484+
master->flags |= SPI_CONTROLLER_MUST_TX;
520485
}
521486
}
522487

0 commit comments

Comments
 (0)