lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [day] [month] [year] [list]
Date:	Fri, 05 Jun 2009 15:40:42 +0200
From:	Richard Röjfors 
	<richard.rojfors.ext@...ean-labs.com>
To:	linux-kernel@...r.kernel.org
Cc:	Andrew Morton <akpm@...ux-foundation.org>
Subject: [PATCH 4/9] MFD: Adding Timberdale DMA driver

Support for the Timberdale FPGA internal DMA engine

This driver gives other drivers the possibility to start DMA directly
between IP block inside the FPGA and the main memory

Signed-off-by: Richard Röjfors <richard.rojfors.ext@...ean-labs.com>
---
Index: linux-2.6.30-rc7/drivers/mfd/Kconfig
===================================================================
--- linux-2.6.30-rc7/drivers/mfd/Kconfig	(revision 861)
+++ linux-2.6.30-rc7/drivers/mfd/Kconfig	(working copy)
@@ -241,6 +241,13 @@
 	 Say yes here if you want to include support GPIO for pins on
 	 the PCF50633 chip.

+config MFD_TIMBERDALE_DMA
+	tristate "Support for timberdale DMA"
+	depends on MFD_TIMBERDALE
+	---help---
+	Add support the DMA block inside the timberdale FPGA. This to be able
+	to do DMA transfers directly to some of the blocks inside the FPGA
+
 endmenu

 menu "Multimedia Capabilities Port drivers"
Index: linux-2.6.30-rc7/drivers/mfd/timbdma.c
===================================================================
--- linux-2.6.30-rc7/drivers/mfd/timbdma.c	(revision 0)
+++ linux-2.6.30-rc7/drivers/mfd/timbdma.c	(revision 864)
@@ -0,0 +1,302 @@
+/*
+ * timbdma.c timberdale FPGA DMA driver
+ * Copyright (c) 2009 Intel Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/* Supports:
+ * Timberdale FPGA DMA engine
+ */
+
+#include <linux/version.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+
+#include <linux/mfd/timbdma.h>
+
+static struct timbdma_dev *self_g;
+
+static irqreturn_t timbdma_handleinterrupt(int irq, void *devid)
+{
+	struct timbdma_dev *dev = (struct timbdma_dev *)devid;
+	int ipr;
+	int i;
+
+	ipr = ioread32(dev->membase + timbdma_ctrlmap_TIMBPEND);
+
+	/* ack */
+	iowrite32(ipr, dev->membase + timbdma_ctrlmap_TIMBSTATUS);
+
+	/* call the callbacks */
+	for (i = 0; i < DMA_IRQS; i++) {
+		int mask = 1 << i;
+		if ((ipr & mask) && dev->callbacks[i])
+			dev->callbacks[i](mask, dev->callback_data[i]);
+	}
+
+	if (ipr)
+		return IRQ_HANDLED;
+	else
+		return IRQ_NONE;
+}
+
+
+void timb_start_dma(u32 flag, unsigned long buf, int len, int bytes_per_row)
+{
+	int i;
+	unsigned long irqflags;
+	struct timbdma_dev *dev = self_g;
+
+	spin_lock_irqsave(&dev->lock, irqflags);
+
+	/* now enable the DMA transfer */
+	for (i = 0; i < DMA_IRQS; i++)
+		if (flag & (1 << i)) {
+			u32 offset = i / 2 * 0x40;
+
+			if (!(i % 2)) {
+				/* RX */
+				/* bytes per row */
+				iowrite32(bytes_per_row, dev->membase + offset +
+					timbdma_dmacfg_BPERROW);
+				/* address high */
+				iowrite32(0, dev->membase + offset +
+					timbdma_dmacfg_RXSTARTH);
+				/* address low */
+				iowrite32(buf, dev->membase + offset +
+					timbdma_dmacfg_RXSTARTL);
+				/* Length */
+				iowrite32(len, dev->membase + offset +
+					timbdma_dmacfg_RXLENGTH);
+				/* Clear rx sw read pointer */
+				iowrite32(0, dev->membase + offset +
+					timbdma_dmacfg_RXSWRP);
+				/* enable the transfer */
+				iowrite32(1, dev->membase + offset +
+					timbdma_dmacfg_RXENABLE);
+			} else {
+				/* TX */
+				/* address high */
+				iowrite32(0, dev->membase + offset +
+					timbdma_dmacfg_TXSTARTH);
+				/* address low */
+				iowrite32(buf, dev->membase + offset +
+					timbdma_dmacfg_TXSTARTL);
+				/* Length */
+				iowrite32(len, dev->membase + offset +
+					timbdma_dmacfg_TXLENGTH);
+				/* Set tx sw write pointer */
+				iowrite32(len, dev->membase + offset +
+					timbdma_dmacfg_TXSWWP);
+			}
+
+			/* only allow one bit in the flag field */
+			break;
+		}
+	spin_unlock_irqrestore(&dev->lock, irqflags);
+}
+EXPORT_SYMBOL(timb_start_dma);
+
+void *timb_stop_dma(u32 flags)
+{
+	int i;
+	unsigned long irqflags;
+	struct timbdma_dev *dev = self_g;
+	void *result = 0;
+
+	spin_lock_irqsave(&dev->lock, irqflags);
+
+	/* now disable the DMA transfers */
+	for (i = 0; i < DMA_IRQS; i++)
+		if (flags & (1 << i)) {
+			/*
+				RX enable registers are located at:
+				0x14
+				0x54
+				0x94
+
+				TX SW pointer registers are located at:
+				0x24
+				0x64
+			*/
+			u32 offset = i / 2 * 0x40;
+			u32 result_offset = offset;
+			if (!(i % 2)) {
+				/* even -> RX enable */
+				offset += timbdma_dmacfg_RXENABLE;
+				result_offset += timbdma_dmacfg_RXFPGAWP;
+			} else {
+				/* odd -> TX SW pointer reg */
+				offset += timbdma_dmacfg_TXSWWP;
+				result_offset = timbdma_dmacfg_TXFPGARP;
+			}
+
+			iowrite32(0, dev->membase + offset);
+			/* check how far the FPGA has written/read */
+			result = (void *)ioread32(dev->membase + result_offset);
+		}
+
+	/* ack any pending IRQs */
+	iowrite32(flags, dev->membase + timbdma_ctrlmap_TIMBSTATUS);
+
+	spin_unlock_irqrestore(&dev->lock, irqflags);
+
+	return result;
+}
+EXPORT_SYMBOL(timb_stop_dma);
+
+void timb_set_dma_interruptcb(u32 flags, timbdma_interruptcb icb, void *data)
+{
+	int i;
+	unsigned long irqflags;
+	struct timbdma_dev *dev = self_g;
+	u32 ier;
+
+	spin_lock_irqsave(&dev->lock, irqflags);
+
+	for (i = 0; i < DMA_IRQS; i++)
+		if (flags & (1 << i)) {
+			dev->callbacks[i] = icb;
+			dev->callback_data[i] = data;
+		}
+
+	/* Ack any pending IRQ */
+	iowrite32(flags, dev->membase + timbdma_ctrlmap_TIMBSTATUS);
+
+	/* if a null callback is given -> clear interrupt, else -> enable */
+	ier = ioread32(dev->membase + timbdma_ctrlmap_TIMBENABLE);
+	if (icb != NULL)
+		ier |= flags;
+	else
+		ier &= ~flags;
+	iowrite32(ier, dev->membase + timbdma_ctrlmap_TIMBENABLE);
+
+	spin_unlock_irqrestore(&dev->lock, irqflags);
+}
+EXPORT_SYMBOL(timb_set_dma_interruptcb);
+
+static int timbdma_probe(struct platform_device *dev)
+{
+	int err, irq;
+	struct timbdma_dev *self;
+	struct resource *iomem;
+
+	iomem = platform_get_resource(dev, IORESOURCE_MEM, 0);
+	if (!iomem) {
+		err = -EINVAL;
+		goto err_mem;
+	}
+
+	self = kzalloc(sizeof(*self), GFP_KERNEL);
+	if (!self) {
+		err = -EINVAL;
+		goto err_mem;
+	}
+
+	spin_lock_init(&self->lock);
+
+	if (!request_mem_region(iomem->start,
+		resource_size(iomem), "timb-dma")) {
+		err = -EBUSY;
+		goto err_request;
+	}
+
+	self->membase = ioremap(iomem->start, resource_size(iomem));
+	if (!self->membase) {
+		printk(KERN_ERR "timbdma: Failed to remap I/O memory\n");
+		err = -ENOMEM;
+		goto err_ioremap;
+	}
+
+	/* register interrupt */
+	irq = platform_get_irq(dev, 0);
+	if (irq < 0) {
+		err = irq;
+		goto err_get_irq;
+	}
+
+	/* request IRQ */
+	err = request_irq(irq, timbdma_handleinterrupt, IRQF_SHARED,
+			  "timb-dma", self);
+	if (err) {
+		printk(KERN_ERR "timbdma: Failed to request IRQ\n");
+		goto err_get_irq;
+	}
+
+	platform_set_drvdata(dev, self);
+
+	/* assign the global pointer */
+	self_g = self;
+
+	return 0;
+
+err_get_irq:
+	iounmap(self->membase);
+err_ioremap:
+	release_mem_region(iomem->start, resource_size(iomem));
+err_request:
+	kfree(self);
+err_mem:
+	printk(KERN_ERR "timberdale: Failed to register Timberdale DMA: %d\n",
+		err);
+
+	return err;
+}
+
+static int timbdma_remove(struct platform_device *dev)
+{
+	struct timbdma_dev *self = platform_get_drvdata(dev);
+	struct resource *iomem = platform_get_resource(dev, IORESOURCE_MEM, 0);
+
+	free_irq(platform_get_irq(dev, 0), self);
+	iounmap(self->membase);
+	release_mem_region(iomem->start, resource_size(iomem));
+	kfree(self);
+	self_g = NULL;
+	return 0;
+}
+
+static struct platform_driver timbdma_platform_driver = {
+	.driver = {
+		.name	= "timb-dma",
+		.owner	= THIS_MODULE,
+	},
+	.probe		= timbdma_probe,
+	.remove		= timbdma_remove,
+};
+
+/*--------------------------------------------------------------------------*/
+
+static int __init timbdma_init(void)
+{
+	self_g = NULL;
+	return platform_driver_register(&timbdma_platform_driver);
+}
+
+static void __exit timbdma_exit(void)
+{
+	platform_driver_unregister(&timbdma_platform_driver);
+}
+
+module_init(timbdma_init);
+module_exit(timbdma_exit);
+
+MODULE_DESCRIPTION("Timberdale DMA driver");
+MODULE_AUTHOR("Mocean Laboratories <info@...ean-labs.com>");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:timb-dma");
+
Index: linux-2.6.30-rc7/drivers/mfd/Makefile
===================================================================
--- linux-2.6.30-rc7/drivers/mfd/Makefile	(revision 861)
+++ linux-2.6.30-rc7/drivers/mfd/Makefile	(working copy)
@@ -40,4 +40,6 @@

 obj-$(CONFIG_MFD_PCF50633)	+= pcf50633-core.o
 obj-$(CONFIG_PCF50633_ADC)	+= pcf50633-adc.o
-obj-$(CONFIG_PCF50633_GPIO)	+= pcf50633-gpio.o
\ No newline at end of file
+obj-$(CONFIG_PCF50633_GPIO)	+= pcf50633-gpio.o
+
+obj-$(CONFIG_MFD_TIMBERDALE_DMA)	+= timbdma.o
Index: linux-2.6.30-rc7/include/linux/mfd/timbdma.h
===================================================================
--- linux-2.6.30-rc7/include/linux/mfd/timbdma.h	(revision 0)
+++ linux-2.6.30-rc7/include/linux/mfd/timbdma.h	(revision 889)
@@ -0,0 +1,76 @@
+/*
+ * timbdma.h timberdale FPGA DMA driver defines
+ * Copyright (c) 2009 Intel Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/* Supports:
+ * Timberdale FPGA DMA engine
+ */
+
+#ifndef _TIMBDMA_H
+#define _TIMBDMA_H
+
+#include <linux/spinlock.h>
+
+
+#define DMA_IRQ_UART_RX		0x01
+#define DMA_IRQ_UART_TX		0x02
+#define DMA_IRQ_MLB_RX		0x04
+#define DMA_IRQ_MLB_TX		0x08
+#define DMA_IRQ_VIDEO_RX	0x10
+#define DMA_IRQ_VIDEO_DROP	0x20
+#define DMA_IRQS		6
+
+
+typedef int (*timbdma_interruptcb)(u32 flag, void *data);
+
+#define timbdma_ctrlmap_DMACFGBTUART	0x000000
+#define timbdma_ctrlmap_DMACFGMLBSY	0x000040
+#define timbdma_ctrlmap_DMACFGVIDEO	0x000080
+#define timbdma_ctrlmap_TIMBSTATUS	0x080000
+#define timbdma_ctrlmap_TIMBPEND	0x080004
+#define timbdma_ctrlmap_TIMBENABLE	0x080008
+#define timbdma_ctrlmap_VIDEOBUFFER	0x200000
+
+#define timbdma_dmacfg_RXSTARTH	0x00
+#define timbdma_dmacfg_RXSTARTL	0x04
+#define timbdma_dmacfg_RXLENGTH	0x08
+#define timbdma_dmacfg_RXFPGAWP	0x0C
+#define timbdma_dmacfg_RXSWRP	0x10
+#define timbdma_dmacfg_RXENABLE	0x14
+#define timbdma_dmacfg_TXSTARTH	0x18
+#define timbdma_dmacfg_TXSTARTL	0x1C
+#define timbdma_dmacfg_TXLENGTH	0x20
+#define timbdma_dmacfg_TXSWWP	0x24
+#define timbdma_dmacfg_TXFPGARP	0x28
+#define timbdma_dmacfg_TXBEFINT	0x2C
+#define timbdma_dmacfg_BPERROW	0x30
+
+struct timbdma_dev {
+	void __iomem		*membase;
+	timbdma_interruptcb	callbacks[DMA_IRQS];
+	void			*callback_data[DMA_IRQS];
+	spinlock_t		lock; /* mutual exclusion */
+};
+
+void timb_start_dma(u32 flag, unsigned long buf, int len, int bytes_per_row);
+
+void *timb_stop_dma(u32 flags);
+
+void timb_set_dma_interruptcb(u32 flags, timbdma_interruptcb icb, void *data);
+
+#endif /* _TIMBDMA_H */
+
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ