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>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date:	Wed, 25 Mar 2015 10:51:55 +0100
From:	Holger Dengler <dengler@...utronix.de>
To:	linux-kernel@...r.kernel.org
Cc:	Peter Mahler <mahler@...ug.com>, Juergen Bubeck <bubeck@...ug.com>,
	Benedikt Spranger <b.spranger@...utronix.de>,
	Holger Dengler <dengler@...utronix.de>,
	Samuel Ortiz <sameo@...ux.intel.com>,
	Lee Jones <lee.jones@...aro.org>
Subject: [PATCH 06/11] mfd: flexcard: add DMA interrupt domain

From: Benedikt Spranger <b.spranger@...utronix.de>

The Flexcard comprise an interrupt controller for the attached
tinys, timer, a Flexray related trigger and a second one for DMA.
Both controllers share a single IRQ line.

Add an interrupt domain for the DMA Controller interrupts.

Signed-off-by: Holger Dengler <dengler@...utronix.de>
Signed-off-by: Benedikt Spranger <b.spranger@...utronix.de>
cc: Samuel Ortiz <sameo@...ux.intel.com>
cc: Lee Jones <lee.jones@...aro.org>
---
 drivers/mfd/flexcard/irq.c   | 95 +++++++++++++++++++++++++++++++++++++++++---
 drivers/mfd/flexcard/irq.h   | 11 +++++
 include/linux/mfd/flexcard.h | 23 +++++++++++
 3 files changed, 124 insertions(+), 5 deletions(-)

diff --git a/drivers/mfd/flexcard/irq.c b/drivers/mfd/flexcard/irq.c
index fefcb24..17e8b2c 100644
--- a/drivers/mfd/flexcard/irq.c
+++ b/drivers/mfd/flexcard/irq.c
@@ -27,11 +27,13 @@
 static irqreturn_t flexcard_demux(int irq, void *data)
 {
 	struct flexcard_device *priv = data;
-	u32 stat;
+	u32 stat, dma_stat;
 	int i, cur;
 
 	stat = readl(&priv->conf->irs);
-	if (!stat)
+	dma_stat = readl(&priv->conf->dma_irsr);
+
+	if (!stat && !dma_stat)
 		return IRQ_NONE;
 
 	for (i = 0; i < NR_FLEXCARD_IRQ; i++) {
@@ -41,6 +43,15 @@ static irqreturn_t flexcard_demux(int irq, void *data)
 				generic_handle_irq(cur);
 		}
 	}
+
+	for (i = 0; i < NR_FLEXCARD_DMA_IRQ; i++) {
+		if (dma_stat & flexcard_dma_irq_tab[i].status) {
+			cur = irq_find_mapping(priv->dma_domain, i);
+			if (cur)
+				generic_handle_irq(cur);
+		}
+	}
+
 	return IRQ_HANDLED;
 }
 
@@ -125,6 +136,63 @@ static struct irq_domain_ops flexcard_irq_domain_ops = {
 	.map = flexcard_irq_domain_map,
 };
 
+static void flexcard_dma_irq_ack(struct irq_data *d)
+{
+	struct flexcard_device *priv = irq_data_get_irq_chip_data(d);
+
+	writel(flexcard_dma_irq_tab[d->hwirq].reset, &priv->conf->dma_irsr);
+}
+
+static void flexcard_dma_irq_mask(struct irq_data *d)
+{
+	struct flexcard_device *priv = irq_data_get_irq_chip_data(d);
+	unsigned long flags;
+	u32 irer;
+
+	raw_spin_lock_irqsave(&priv->irq_lock, flags);
+	irer = readl(&priv->conf->dma_irer);
+	irer &= ~flexcard_dma_irq_tab[d->hwirq].enable;
+	writel(irer, &priv->conf->dma_irer);
+	raw_spin_unlock_irqrestore(&priv->irq_lock, flags);
+}
+
+static void flexcard_dma_irq_unmask(struct irq_data *d)
+{
+	struct flexcard_device *priv = irq_data_get_irq_chip_data(d);
+	unsigned long flags;
+	u32 irer;
+
+	raw_spin_lock_irqsave(&priv->irq_lock, flags);
+	irer = readl(&priv->conf->dma_irer);
+	irer |= FLEXCARD_DMA_IRER_DIRE | flexcard_dma_irq_tab[d->hwirq].enable;
+	writel(irer, &priv->conf->dma_irer);
+	raw_spin_unlock_irqrestore(&priv->irq_lock, flags);
+}
+
+static struct irq_chip flexcard_dma_irq_chip = {
+	.name		= "flexcard_dma_irq",
+	.irq_ack	= flexcard_dma_irq_ack,
+	.irq_mask	= flexcard_dma_irq_mask,
+	.irq_unmask	= flexcard_dma_irq_unmask,
+};
+
+static int flexcard_dma_irq_domain_map(struct irq_domain *d, unsigned int irq,
+				       irq_hw_number_t hw)
+{
+	struct flexcard_device *priv = d->host_data;
+
+	irq_set_chip_and_handler_name(irq, &flexcard_dma_irq_chip,
+				      handle_level_irq, "flexcard-dma");
+	irq_set_chip_data(irq, priv);
+	irq_modify_status(irq, IRQ_NOREQUEST | IRQ_NOAUTOEN, IRQ_NOPROBE);
+
+	return 0;
+}
+
+static struct irq_domain_ops flexcard_dma_irq_domain_ops = {
+	.map = flexcard_dma_irq_domain_map,
+};
+
 int flexcard_setup_irq(struct pci_dev *pdev)
 {
 	struct flexcard_device *priv = pci_get_drvdata(pdev);
@@ -143,12 +211,27 @@ int flexcard_setup_irq(struct pci_dev *pdev)
 		dev_err(&pdev->dev, "could not request irq domain\n");
 		return -ENODEV;
 	}
-
 	priv->irq_domain = domain;
 
+	domain = irq_domain_add_linear(NULL, NR_FLEXCARD_DMA_IRQ,
+				       &flexcard_dma_irq_domain_ops, priv);
+	if (!domain) {
+		dev_err(&pdev->dev, "could not request dma irq domain\n");
+		ret = -ENODEV;
+		goto out_irq;
+	}
+	priv->dma_domain = domain;
+
 	ret = flexcard_req_irq(pdev);
 	if (ret)
-		irq_domain_remove(priv->dma_domain);
+		goto out_dma;
+
+	return 0;
+
+out_dma:
+	irq_domain_remove(priv->dma_domain);
+out_irq:
+	irq_domain_remove(priv->irq_domain);
 
 	return ret;
 }
@@ -161,7 +244,9 @@ void flexcard_remove_irq(struct pci_dev *pdev)
 	writel(0, &priv->conf->irc);
 	writel(0, &priv->conf->dma_irer);
 
+	irq_domain_remove(priv->dma_domain);
+	irq_domain_remove(priv->irq_domain);
+
 	free_irq(pdev->irq, priv);
 	pci_disable_msi(pdev);
-	irq_domain_remove(priv->irq_domain);
 }
diff --git a/drivers/mfd/flexcard/irq.h b/drivers/mfd/flexcard/irq.h
index b18fb5b..0e6fe18 100644
--- a/drivers/mfd/flexcard/irq.h
+++ b/drivers/mfd/flexcard/irq.h
@@ -1,6 +1,8 @@
 #ifndef FLEXCARD_IRQ_H
 #define FLEXCARD_IRQ_H
 
+#define FLEXCARD_DMA_IRER_DIRE		(1 << 31)
+
 struct flexcard_irq_tab {
 	u32 enable;
 	u32 reset;
@@ -47,4 +49,13 @@ static const struct flexcard_irq_tab flexcard_irq_tab[] = {
 
 #define NR_FLEXCARD_IRQ		ARRAY_SIZE(flexcard_irq_tab)
 
+static const struct flexcard_irq_tab flexcard_dma_irq_tab[] = {
+	to_irq_tab_ack(0, 0, 0),	/* DMA_C0  */
+	to_irq_tab_ack(1, 1, 1),	/* DMA_TE  */
+	to_irq_tab_ack(4, 4, 4),	/* DMA_TI  */
+	to_irq_tab_ack(5, 5, 5),	/* DMA_CBL */
+};
+
+#define NR_FLEXCARD_DMA_IRQ	ARRAY_SIZE(flexcard_dma_irq_tab)
+
 #endif /* FLEXCARD_IRQ_H */
diff --git a/include/linux/mfd/flexcard.h b/include/linux/mfd/flexcard.h
index f5b789f..f9b0962 100644
--- a/include/linux/mfd/flexcard.h
+++ b/include/linux/mfd/flexcard.h
@@ -30,6 +30,7 @@ struct flexcard_device {
 	struct miscdevice dev;
 	struct kref ref;
 	struct irq_domain *irq_domain;
+	struct irq_domain *dma_domain;
 	int cardnr;
 	char name[FLEXCARD_MAX_NAME];
 };
@@ -39,4 +40,26 @@ enum flexcard_cell_id {
 	FLEXCARD_CELL_FLEXRAY,
 };
 
+#define FLEXCARD_IRQ_CC1CCYS_OFF	0
+#define FLEXCARD_IRQ_CC2CCYS_OFF	1
+#define FLEXCARD_IRQ_CC3CCYS_OFF	2
+#define FLEXCARD_IRQ_CC4CCYS_OFF	3
+#define FLEXCARD_IRQ_WAKE4A_OFF		4
+#define FLEXCARD_IRQ_WAKE4B_OFF		5
+#define FLEXCARD_IRQ_WAKE3A_OFF		6
+#define FLEXCARD_IRQ_WAKE3B_OFF		7
+#define FLEXCARD_IRQ_WAKE2A_OFF		8
+#define FLEXCARD_IRQ_WAKE2B_OFF		9
+#define FLEXCARD_IRQ_WAKE1A_OFF		10
+#define FLEXCARD_IRQ_WAKE1B_OFF		11
+#define FLEXCARD_IRQ_CC1T0_OFF		12
+#define FLEXCARD_IRQ_CC2T0_OFF		13
+#define FLEXCARD_IRQ_CC3T0_OFF		14
+#define FLEXCARD_IRQ_CC4T0_OFF		15
+
+#define FLEXCARD_DMA_IRQ_CO		0
+#define FLEXCARD_DMA_IRQ_TE		1
+#define FLEXCARD_DMA_IRQ_TI		2
+#define FLEXCARD_DMA_IRQ_CBL		3
+
 #endif /* FLEXCARD_H */
-- 
2.1.4

--
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