[PATCH 16/30] leon, grpci2: prepare for GRPCI2DMA driver
Daniel Hellstrom
daniel at gaisler.com
Thu Apr 13 19:31:25 UTC 2017
From: Javier Jalle <javier.jalle at gaisler.com>
---
c/src/lib/libbsp/sparc/shared/pci/grpci2.c | 110 +++++++++++++++++++----------
1 file changed, 72 insertions(+), 38 deletions(-)
diff --git a/c/src/lib/libbsp/sparc/shared/pci/grpci2.c b/c/src/lib/libbsp/sparc/shared/pci/grpci2.c
index 7556f68..eb62226 100644
--- a/c/src/lib/libbsp/sparc/shared/pci/grpci2.c
+++ b/c/src/lib/libbsp/sparc/shared/pci/grpci2.c
@@ -170,44 +170,6 @@ struct grpci2_regs {
#define STS_ITGTABRT (1<<13)
#define STS_IPARERR (1<<12)
-struct grpci2_bd_chan {
- volatile unsigned int ctrl; /* 0x00 DMA Control */
- volatile unsigned int nchan; /* 0x04 Next DMA Channel Address */
- volatile unsigned int nbd; /* 0x08 Next Data Descriptor in channel */
- volatile unsigned int res; /* 0x0C Reserved */
-};
-
-#define BD_CHAN_EN (1<<BD_CHAN_EN_BIT)
-#define BD_CHAN_ID (0x3<<BD_CHAN_ID_BIT)
-#define BD_CHAN_TYPE (0x3<<BD_CHAN_TYPE_BIT)
-#define BD_CHAN_BDCNT (0xffff<<BD_CHAN_BDCNT_BIT)
-#define BD_CHAN_EN_BIT 31
-#define BD_CHAN_ID_BIT 22
-#define BD_CHAN_TYPE_BIT 20
-#define BD_CHAN_BDCNT_BIT 0
-
-struct grpci2_bd_data {
- volatile unsigned int ctrl; /* 0x00 DMA Data Control */
- volatile unsigned int pci_adr; /* 0x04 PCI Start Address */
- volatile unsigned int ahb_adr; /* 0x08 AHB Start address */
- volatile unsigned int next; /* 0x0C Next Data Descriptor in channel */
-};
-
-#define BD_DATA_EN (0x1<<BD_DATA_EN_BIT)
-#define BD_DATA_IE (0x1<<BD_DATA_IE_BIT)
-#define BD_DATA_DR (0x1<<BD_DATA_DR_BIT)
-#define BD_DATA_BE (0x1<<BD_DATA_BE_BIT)
-#define BD_DATA_TYPE (0x3<<BD_DATA_TYPE_BIT)
-#define BD_DATA_ER (0x1<<BD_DATA_ER_BIT)
-#define BD_DATA_LEN (0xffff<<BD_DATA_LEN_BIT)
-#define BD_DATA_EN_BIT 31
-#define BD_DATA_IE_BIT 30
-#define BD_DATA_DR_BIT 29
-#define BD_DATA_BE_BIT 28
-#define BD_DATA_TYPE_BIT 20
-#define BD_DATA_ER_BIT 19
-#define BD_DATA_LEN_BIT 0
-
/* GRPCI2 Capability */
struct grpci2_cap_first {
unsigned int ctrl;
@@ -260,6 +222,7 @@ struct grpci2_priv {
unsigned char ver;
char irq;
char irq_mode; /* IRQ Mode from CAPSTS REG */
+ char irq_dma; /* IRQ Index for DMA */
char bt_enabled;
unsigned int irq_mask;
unsigned int latency_timer;
@@ -278,12 +241,17 @@ struct grpci2_priv {
struct drvmgr_map_entry maps_down[2];
struct pcibus_config config;
+ /* DMA interrupts */
+ void (*dma_isr)(void *data);
+ void *dma_isr_arg;
+
SPIN_DECLARE(devlock)
};
int grpci2_init1(struct drvmgr_dev *dev);
int grpci2_init3(struct drvmgr_dev *dev);
void grpci2_err_isr(void *arg);
+void grpci2_dma_isr(void *arg);
/* GRPCI2 DRIVER */
@@ -317,6 +285,19 @@ struct amba_drv_info grpci2_info =
&grpci2_ids[0]
};
+/* Defaults to do nothing - user can override this function
+ * by including the DMA DRIVER.
+ */
+int __attribute__((weak)) grpci2dma_init(void * regs, void isr_register( void (*isr)(void *), void * arg));
+
+int grpci2dma_init(void * regs, void isr_register( void (*isr)(void *), void * arg))
+{
+ return 0;
+}
+
+/* Prototype of grpci2_dma_isr_register function */
+static void grpci2_dma_isr_register( void (*isr)(void *), void * arg);
+
void grpci2_register_drv(void)
{
DBG("Registering GRPCI2 driver\n");
@@ -662,6 +643,24 @@ void grpci2_err_isr(void *arg)
}
}
+/* PCI DMA Interrupt handler, called when there may be a PCI DMA interrupt.
+ */
+void grpci2_dma_isr(void *arg)
+{
+ struct grpci2_priv *priv = arg;
+ unsigned int sts = (priv->regs->sts_cap & (STS_IDMAERR | STS_IDMA));
+
+ /* Clear Interrupt if taken*/
+ if (sts != 0){
+ /* Clear IDMAERR and IDMA bits */
+ priv->regs->sts_cap = (STS_IDMAERR | STS_IDMA);
+ /* Clear DRVMGR interrupt */
+ drvmgr_interrupt_clear(priv->dev, priv->irq_dma);
+ /* Call DMA driver ISR */
+ (priv->dma_isr)(priv->dma_isr_arg);
+ }
+}
+
static int grpci2_hw_init(struct grpci2_priv *priv)
{
struct grpci2_regs *regs = priv->regs;
@@ -957,6 +956,11 @@ int grpci2_init3(struct drvmgr_dev *dev)
/* Install and Enable PCI Error interrupt handler */
drvmgr_interrupt_register(dev, 0, "grpci2", grpci2_err_isr, priv);
+ /* Initialize DMA driver (if supported) */
+ if (priv->regs->sts_cap & STS_DMA){
+ grpci2dma_init((void *) &(priv->regs->dma_ctrl), grpci2_dma_isr_register);
+ }
+
/* Unmask Error IRQ and all PCI interrupts at PCI Core. For this to be
* safe every PCI board have to be resetted (no IRQ generation) before
* Global IRQs are enabled (Init is reached or similar)
@@ -965,3 +969,33 @@ int grpci2_init3(struct drvmgr_dev *dev)
return DRVMGR_OK;
}
+
+static void grpci2_dma_isr_register( void (*isr)(void *), void * arg)
+{
+ struct grpci2_priv *priv = grpci2priv;
+
+ /* Handle unregistration */
+ if (priv->dma_isr != NULL) {
+ drvmgr_interrupt_unregister(priv->dev, priv->irq_dma, grpci2_dma_isr, priv);
+ /* Uninstall user ISR */
+ priv->dma_isr = NULL;
+ priv->dma_isr_arg = NULL;
+ }
+
+ if (isr == NULL)
+ return;
+
+ /* Install user ISR */
+ priv->dma_isr_arg = arg;
+ priv->dma_isr = isr;
+
+ /* Install and Enable PCI DMA interrupt handler */
+ if (priv->irq_mode == 1) {
+ priv->irq_dma = 1;
+ } else if (priv->irq_mode == 3) {
+ priv->irq_dma = 4;
+ } else {
+ priv->irq_dma = 0;
+ }
+ drvmgr_interrupt_register(priv->dev, priv->irq_dma, "grpci2dma", grpci2_dma_isr, priv);
+}
--
2.7.4
More information about the devel
mailing list