>From 6e70cb81c75ebb0ac7897d07c0f12d80505bb22b Mon Sep 17 00:00:00 2001
From: Matt Sickler
Date: Mon, 22 Apr 2019 09:24:03 -0500
Subject: [PATCH] staging: kpc2000: Add DMA driver
Add Daktronics DMA driver. I've added the SPDX license identifiers, Kconfig
entry, and cleaned up as many of the warnings as I could.
I'm not sure what should be done about the AIO "support" code in this driver.
It's currently guarded by an #ifdef CONFIG_KPC_DMA_AIO. Even if that option
was turned on, the code doesn't compile (aio_complete() was removed since
the original version of this driver) and it probably doesn't work right even
if it did compile. Maybe it's best to just remove it completely?
---
drivers/staging/kpc2000/Kconfig | 11 +
drivers/staging/kpc2000/Makefile | 1 +
drivers/staging/kpc2000/kpc_dma/Makefile | 6 +
drivers/staging/kpc2000/kpc_dma/dma.c| 264 ++
drivers/staging/kpc2000/kpc_dma/fileops.c| 420 +++
drivers/staging/kpc2000/kpc_dma/kpc_dma_driver.c | 248 +
drivers/staging/kpc2000/kpc_dma/kpc_dma_driver.h | 220
drivers/staging/kpc2000/kpc_dma/uapi.h | 11 +
8 files changed, 1181 insertions(+)
create mode 100644 drivers/staging/kpc2000/kpc_dma/Makefile
create mode 100644 drivers/staging/kpc2000/kpc_dma/dma.c
create mode 100644 drivers/staging/kpc2000/kpc_dma/fileops.c
create mode 100644 drivers/staging/kpc2000/kpc_dma/kpc_dma_driver.c
create mode 100644 drivers/staging/kpc2000/kpc_dma/kpc_dma_driver.h
create mode 100644 drivers/staging/kpc2000/kpc_dma/uapi.h
diff --git a/drivers/staging/kpc2000/Kconfig b/drivers/staging/kpc2000/Kconfig
index 926e770d6e0e..fb5922928f47 100644
--- a/drivers/staging/kpc2000/Kconfig
+++ b/drivers/staging/kpc2000/Kconfig
@@ -44,3 +44,14 @@ config KPC2000_I2C
If unsure, say N.
+config KPC2000_DMA
+ tristate "Daktronics KPC DMA controller"
+ depends on KPC2000
+ help
+ Say Y here if you wish to support the Daktronics DMA controller.
+
+ To compile this driver as a module, choose M here: the module
+ will be called kpc2000_dma
+
+ If unsure, say N.
+
diff --git a/drivers/staging/kpc2000/Makefile b/drivers/staging/kpc2000/Makefile
index 6fcb2ee7b27d..1e48e9df1329 100644
--- a/drivers/staging/kpc2000/Makefile
+++ b/drivers/staging/kpc2000/Makefile
@@ -3,3 +3,4 @@
obj-$(CONFIG_KPC2000) += kpc2000/
obj-$(CONFIG_KPC2000_I2C) += kpc_i2c/
obj-$(CONFIG_KPC2000_SPI) += kpc_spi/
+obj-$(CONFIG_KPC2000_DMA) += kpc_dma/
diff --git a/drivers/staging/kpc2000/kpc_dma/Makefile
b/drivers/staging/kpc2000/kpc_dma/Makefile
new file mode 100644
index ..fe5db532c8c8
--- /dev/null
+++ b/drivers/staging/kpc2000/kpc_dma/Makefile
@@ -0,0 +1,6 @@
+# SPDX-License-Identifier: GPL-2.0
+
+obj-m := kpc_dma.o
+kpc_dma-objs += dma.o
+kpc_dma-objs += fileops.o
+kpc_dma-objs += kpc_dma_driver.o
diff --git a/drivers/staging/kpc2000/kpc_dma/dma.c
b/drivers/staging/kpc2000/kpc_dma/dma.c
new file mode 100644
index ..6959bac11388
--- /dev/null
+++ b/drivers/staging/kpc2000/kpc_dma/dma.c
@@ -0,0 +1,264 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include "kpc_dma_driver.h"
+
+/** IRQ Handlers **/
+static
+irqreturn_t ndd_irq_handler(int irq, void *dev_id)
+{
+ struct kpc_dma_device *ldev = (struct kpc_dma_device*)dev_id;
+
+ if ((GetEngineControl(ldev) & ENG_CTL_IRQ_ACTIVE) ||
(ldev->desc_completed->MyDMAAddr != GetEngineCompletePtr(ldev)))
+ schedule_work(>irq_work);
+
+ return IRQ_HANDLED;
+}
+
+static
+void ndd_irq_worker(struct work_struct *ws)
+{
+ struct kpc_dma_descriptor *cur;
+ struct kpc_dma_device *eng = container_of(ws, struct kpc_dma_device,
irq_work);
+ lock_engine(eng);
+
+ if (GetEngineCompletePtr(eng) == 0)
+ goto out;
+
+ if (eng->desc_completed->MyDMAAddr == GetEngineCompletePtr(eng))
+ goto out;
+
+ cur = eng->desc_completed;
+ do {
+ cur = cur->Next;
+ dev_dbg(>pldev->dev, "Handling completed descriptor %p
(acd = %p)\n", cur, cur->acd);
+ BUG_ON(cur == eng->desc_next); // Ordering failure.
+
+ if (cur->DescControlFlags & DMA_DESC_CTL_SOP){
+ eng->accumulated_bytes = 0;
+ eng->accumulated_flags = 0;
+ }
+
+ eng->accumulated_bytes += cur->DescByteCount;
+ if (cur->DescStatusFlags & DMA_DESC_STS_ERROR)
+ eng->accumulated_flags |= ACD_FLAG_ENG_ACCUM_ERROR;
+
+ if (cur->