[PATCH 01/30] leon, GR-CPCI-GR740: Added peripheral PCI driver
Daniel Hellstrom
daniel at gaisler.com
Thu Apr 13 19:31:10 UTC 2017
From: Javier Jalle <javier.jalle at gaisler.com>
---
c/src/lib/libbsp/sparc/Makefile.am | 2 +
c/src/lib/libbsp/sparc/leon2/Makefile.am | 2 +
c/src/lib/libbsp/sparc/leon2/preinstall.am | 4 +
c/src/lib/libbsp/sparc/leon3/Makefile.am | 2 +
c/src/lib/libbsp/sparc/leon3/preinstall.am | 4 +
.../libbsp/sparc/shared/include/gr_cpci_gr740.h | 61 ++
c/src/lib/libbsp/sparc/shared/pci/gr_cpci_gr740.c | 738 +++++++++++++++++++++
cpukit/libdrvmgr/drvmgr_confdefs.h | 4 +
cpukit/libpci/pci/ids_extra.h | 1 +
cpukit/libpci/pci_bus.h | 1 +
10 files changed, 819 insertions(+)
create mode 100644 c/src/lib/libbsp/sparc/shared/include/gr_cpci_gr740.h
create mode 100644 c/src/lib/libbsp/sparc/shared/pci/gr_cpci_gr740.c
diff --git a/c/src/lib/libbsp/sparc/Makefile.am b/c/src/lib/libbsp/sparc/Makefile.am
index af0df0a..f75790a 100644
--- a/c/src/lib/libbsp/sparc/Makefile.am
+++ b/c/src/lib/libbsp/sparc/Makefile.am
@@ -57,6 +57,7 @@ EXTRA_DIST += shared/include/gr_rasta_spw_router.h
EXTRA_DIST += shared/include/gr_rasta_tmtc.h
EXTRA_DIST += shared/include/gr_tmtc_1553.h
EXTRA_DIST += shared/include/gr_leon4_n2x.h
+EXTRA_DIST += shared/include/gr_cpci_gr740.h
EXTRA_DIST += shared/pci/gr_701.c
EXTRA_DIST += shared/pci/gr_rasta_adcdac.c
EXTRA_DIST += shared/pci/gr_rasta_io.c
@@ -64,6 +65,7 @@ EXTRA_DIST += shared/pci/gr_rasta_spw_router.c
EXTRA_DIST += shared/pci/gr_rasta_tmtc.c
EXTRA_DIST += shared/pci/gr_tmtc_1553.c
EXTRA_DIST += shared/pci/gr_leon4_n2x.c
+EXTRA_DIST += shared/pci/gr_cpci_gr740.c
# DEBUG
EXTRA_DIST += shared/include/debug_defs.h
diff --git a/c/src/lib/libbsp/sparc/leon2/Makefile.am b/c/src/lib/libbsp/sparc/leon2/Makefile.am
index 5ac0e04..bafa626 100644
--- a/c/src/lib/libbsp/sparc/leon2/Makefile.am
+++ b/c/src/lib/libbsp/sparc/leon2/Makefile.am
@@ -112,12 +112,14 @@ include_bsp_HEADERS += ../../sparc/shared/include/gr_rasta_io.h
include_bsp_HEADERS += ../../sparc/shared/include/gr_rasta_spw_router.h
include_bsp_HEADERS += ../../sparc/shared/include/gr_rasta_tmtc.h
include_bsp_HEADERS += ../../sparc/shared/include/gr_leon4_n2x.h
+include_bsp_HEADERS += ../../sparc/shared/include/gr_cpci_gr740.h
libbsp_a_SOURCES += ../../sparc/shared/pci/gr_701.c
libbsp_a_SOURCES += ../../sparc/shared/pci/gr_rasta_adcdac.c
libbsp_a_SOURCES += ../../sparc/shared/pci/gr_rasta_io.c
libbsp_a_SOURCES += ../../sparc/shared/pci/gr_rasta_spw_router.c
libbsp_a_SOURCES += ../../sparc/shared/pci/gr_rasta_tmtc.c
libbsp_a_SOURCES += ../../sparc/shared/pci/gr_leon4_n2x.c
+libbsp_a_SOURCES += ../../sparc/shared/pci/gr_cpci_gr740.c
# B1553BRM
include_bsp_HEADERS += ../../sparc/shared/include/b1553brm.h
diff --git a/c/src/lib/libbsp/sparc/leon2/preinstall.am b/c/src/lib/libbsp/sparc/leon2/preinstall.am
index f4c8ca4..873cc17 100644
--- a/c/src/lib/libbsp/sparc/leon2/preinstall.am
+++ b/c/src/lib/libbsp/sparc/leon2/preinstall.am
@@ -161,6 +161,10 @@ $(PROJECT_INCLUDE)/bsp/gr_leon4_n2x.h: ../../sparc/shared/include/gr_leon4_n2x.h
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/gr_leon4_n2x.h
PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/gr_leon4_n2x.h
+$(PROJECT_INCLUDE)/bsp/gr_cpci_gr740.h: ../../sparc/shared/include/gr_cpci_gr740.h $(PROJECT_INCLUDE)/bsp/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/gr_cpci_gr740.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/gr_cpci_gr740.h
+
$(PROJECT_INCLUDE)/bsp/b1553brm.h: ../../sparc/shared/include/b1553brm.h $(PROJECT_INCLUDE)/bsp/$(dirstamp)
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/b1553brm.h
PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/b1553brm.h
diff --git a/c/src/lib/libbsp/sparc/leon3/Makefile.am b/c/src/lib/libbsp/sparc/leon3/Makefile.am
index f2f690e..9a4737c 100644
--- a/c/src/lib/libbsp/sparc/leon3/Makefile.am
+++ b/c/src/lib/libbsp/sparc/leon3/Makefile.am
@@ -124,6 +124,7 @@ include_bsp_HEADERS += ../../sparc/shared/include/gr_rasta_spw_router.h
include_bsp_HEADERS += ../../sparc/shared/include/gr_rasta_tmtc.h
include_bsp_HEADERS += ../../sparc/shared/include/gr_tmtc_1553.h
include_bsp_HEADERS += ../../sparc/shared/include/gr_leon4_n2x.h
+include_bsp_HEADERS += ../../sparc/shared/include/gr_cpci_gr740.h
libbsp_a_SOURCES += ../../sparc/shared/pci/gr_701.c
libbsp_a_SOURCES += ../../sparc/shared/pci/gr_rasta_adcdac.c
libbsp_a_SOURCES += ../../sparc/shared/pci/gr_rasta_io.c
@@ -131,6 +132,7 @@ libbsp_a_SOURCES += ../../sparc/shared/pci/gr_rasta_spw_router.c
libbsp_a_SOURCES += ../../sparc/shared/pci/gr_rasta_tmtc.c
libbsp_a_SOURCES += ../../sparc/shared/pci/gr_tmtc_1553.c
libbsp_a_SOURCES += ../../sparc/shared/pci/gr_leon4_n2x.c
+libbsp_a_SOURCES += ../../sparc/shared/pci/gr_cpci_gr740.c
# B1553BRM
include_bsp_HEADERS += ../../sparc/shared/include/b1553brm.h
diff --git a/c/src/lib/libbsp/sparc/leon3/preinstall.am b/c/src/lib/libbsp/sparc/leon3/preinstall.am
index 5ef0a63..d9bdf35 100644
--- a/c/src/lib/libbsp/sparc/leon3/preinstall.am
+++ b/c/src/lib/libbsp/sparc/leon3/preinstall.am
@@ -181,6 +181,10 @@ $(PROJECT_INCLUDE)/bsp/gr_leon4_n2x.h: ../../sparc/shared/include/gr_leon4_n2x.h
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/gr_leon4_n2x.h
PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/gr_leon4_n2x.h
+$(PROJECT_INCLUDE)/bsp/gr_cpci_gr740.h: ../../sparc/shared/include/gr_cpci_gr740.h $(PROJECT_INCLUDE)/bsp/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/gr_cpci_gr740.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/gr_cpci_gr740.h
+
$(PROJECT_INCLUDE)/bsp/b1553brm.h: ../../sparc/shared/include/b1553brm.h $(PROJECT_INCLUDE)/bsp/$(dirstamp)
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/b1553brm.h
PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/b1553brm.h
diff --git a/c/src/lib/libbsp/sparc/shared/include/gr_cpci_gr740.h b/c/src/lib/libbsp/sparc/shared/include/gr_cpci_gr740.h
new file mode 100644
index 0000000..55c28ac
--- /dev/null
+++ b/c/src/lib/libbsp/sparc/shared/include/gr_cpci_gr740.h
@@ -0,0 +1,61 @@
+/* GR-CPCI-GR740 PCI Peripheral driver
+ *
+ * COPYRIGHT (c) 2017.
+ * Cobham Gaisler AB.
+ *
+ * The license and distribution terms for this file may be
+ * found in found in the file LICENSE in this distribution or at
+ * http://www.rtems.org/license/LICENSE.
+ *
+ * Configures the GR-CPIC-GR740 interface PCI board in peripheral
+ * mode. This driver provides a AMBA PnP bus by using the general part
+ * of the AMBA PnP bus driver (ambapp_bus.c).
+ *
+ *
+ * Driver resource options:
+ * NAME DEFAULT VALUE
+ * ahbmst2pci _RAM_START AMBA->PCI translation PCI base address
+ * ambaFreq 250000000 (250MHz) AMBA system frequency of GR740
+ * cgEnMask 0x1f (all) Clock gating enable mask
+ *
+ * TODO/UNTESTED
+ * Interrupt testing
+ * bar0 RESOURCE 0x00000000 L2-Cache SDRAM memory
+ * bar1 RESOURCE 0xf0000000 L2-Cache registers
+ */
+
+#ifndef __GR_CPCI_GR740_H__
+#define __GR_CPCI_GR740_H__
+
+#include <drvmgr/drvmgr.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* An array of pointers to GR-CPCI-GR740 resources. The resources will be
+ * used by the drivers controlling the cores on the GR-CPCI-GR740 target
+ * AMBA bus.
+ *
+ * The gr_cpci_gr740_resources is declared weak so that the user can override the
+ * default configuration. The array must be terminated with a NULL resource.
+ */
+extern struct drvmgr_bus_res *gr_cpci_gr740_resources[];
+
+/* Options to gr_cpci_gr740_print function */
+#define GR_CPCI_GR740_OPTIONS_AMBA 0x01 /* Print AMBA bus devices */
+
+/* Print information about all GR-CPCI-GR740 PCI boards */
+void gr_cpci_gr740_print(int options);
+
+/* Print information about one GR-CPCI-GR740 PCI board */
+void gr_cpci_gr740_print_dev(struct drvmgr_dev *dev, int options);
+
+/* Register GR-CPCI-GR740 driver */
+void gr_cpci_gr740_register_drv(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/c/src/lib/libbsp/sparc/shared/pci/gr_cpci_gr740.c b/c/src/lib/libbsp/sparc/shared/pci/gr_cpci_gr740.c
new file mode 100644
index 0000000..3ba55c5
--- /dev/null
+++ b/c/src/lib/libbsp/sparc/shared/pci/gr_cpci_gr740.c
@@ -0,0 +1,738 @@
+/* GR-CPCI-GR740 PCI Target driver.
+ *
+ * COPYRIGHT (c) 2017.
+ * Cobham Gaisler AB.
+ *
+ * The license and distribution terms for this file may be
+ * found in found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * Configures the GR-CPCI-GR740 interface PCI board in peripheral
+ * mode. This driver provides a AMBA PnP bus by using the general part
+ * of the AMBA PnP bus driver (ambapp_bus.c). Based on the
+ * GR-RASTA-IO driver.
+ *
+ *
+ * Driver resource options:
+ * NAME DEFAULT VALUE
+ * ahbmst2pci _RAM_START AMBA->PCI translation PCI base address
+ * ambaFreq 250000000 (250MHz) AMBA system frequency of GR740
+ * cgEnMask 0x1f (all) Clock gating enable mask
+ * bar0 0x00000000 L2-Cache SDRAM memory
+ * bar1 0xf0000000 L2-Cache registers
+ *
+ * TODO/UNTESTED
+ * Interrupt testing
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <bsp.h>
+#include <rtems/bspIo.h>
+#include <pci.h>
+
+#include <ambapp.h>
+#include <grlib.h>
+#include <drvmgr/drvmgr.h>
+#include <drvmgr/ambapp_bus.h>
+#include <drvmgr/pci_bus.h>
+#include <drvmgr/bspcommon.h>
+#include <bsp/genirq.h>
+
+#include <bsp/gr_cpci_gr740.h>
+
+/* Determines which PCI address the AHB masters on the GR740 board will
+ * access when accessing the AHB to PCI window, it should be set so that the
+ * masters can access the HOST RAM.
+ * Default is base of HOST RAM, HOST RAM is mapped 1:1 to PCI memory space.
+ */
+extern unsigned int _RAM_START;
+#define AHBMST2PCIADR (((unsigned int)&_RAM_START) & 0xc0000000)
+
+#define GRPCI2_BAR0_TO_AHB_MAP 0x04
+#define GRPCI2_BAR1_TO_AHB_MAP 0x08
+#define GRPCI2_BAR2_TO_AHB_MAP 0x0c
+#define GRPCI2_PCI_CONFIG 0x20
+#define CAP9_AHBPREF_OFS 0x3c
+
+/* #define DEBUG 1 */
+
+#ifdef DEBUG
+#define DBG(x...) printk(x)
+#else
+#define DBG(x...)
+#endif
+
+int gr_cpci_gr740_init1(struct drvmgr_dev *dev);
+int gr_cpci_gr740_init2(struct drvmgr_dev *dev);
+void gr_cpci_gr740_isr(void *arg);
+
+struct grpci2_regs {
+ volatile unsigned int ctrl; /* 0x00 */
+ volatile unsigned int sts_cap; /* 0x04 */
+ volatile unsigned int ppref; /* 0x08 */
+ volatile unsigned int io_map; /* 0x0C */
+ volatile unsigned int dma_ctrl; /* 0x10 */
+ volatile unsigned int dma_bdbase; /* 0x14 */
+ volatile unsigned int dma_chact; /* 0x18 */
+ int res1; /* 0x1C */
+ volatile unsigned int bars[6]; /* 0x20 */
+ int res2[2]; /* 0x38 */
+ volatile unsigned int ahbmst_map[16]; /* 0x40 */
+};
+
+/* Clock gating unit register layout */
+struct gr740_grcg_regs {
+ volatile unsigned int unlock;
+ volatile unsigned int enable;
+ volatile unsigned int reset;
+ volatile unsigned int cpu_fpu;
+};
+#define CG_MASK 0x3ff
+
+/* Private data structure for driver */
+struct gr_cpci_gr740_priv {
+ /* Driver management */
+ struct drvmgr_dev *dev;
+ char prefix[20];
+
+ /* PCI */
+ pci_dev_t pcidev;
+ struct pci_dev_info *devinfo;
+ uint32_t ahbmst2pci_map;
+
+ /* IRQ */
+ int eirq;
+ genirq_t genirq;
+
+ /* GR-CPCI-GR740 */
+ unsigned int amba_freq_hz;
+ unsigned int cg_en_mask; /* Enabled cores */
+ struct irqmp_regs *irq;
+ struct gr740_grcg_regs *cg; /* Clock-gating unit */
+ struct grpci2_regs *grpci2;
+ struct drvmgr_map_entry bus_maps_up[2];
+ struct drvmgr_map_entry bus_maps_down[4];
+
+ /* AMBA Plug&Play information on GR-CPCI-GR740 */
+ struct ambapp_bus abus;
+ struct ambapp_mmap amba_maps[5];
+ struct ambapp_config config;
+};
+
+int ambapp_gr740_int_register(
+ struct drvmgr_dev *dev,
+ int irq,
+ const char *info,
+ drvmgr_isr handler,
+ void *arg);
+int ambapp_gr740_int_unregister(
+ struct drvmgr_dev *dev,
+ int irq,
+ drvmgr_isr handler,
+ void *arg);
+int ambapp_gr740_int_unmask(
+ struct drvmgr_dev *dev,
+ int irq);
+int ambapp_gr740_int_mask(
+ struct drvmgr_dev *dev,
+ int irq);
+int ambapp_gr740_int_clear(
+ struct drvmgr_dev *dev,
+ int irq);
+int ambapp_gr740_get_params(
+ struct drvmgr_dev *dev,
+ struct drvmgr_bus_params *params);
+
+static struct ambapp_ops ambapp_gr740_ops = {
+ .int_register = ambapp_gr740_int_register,
+ .int_unregister = ambapp_gr740_int_unregister,
+ .int_unmask = ambapp_gr740_int_unmask,
+ .int_mask = ambapp_gr740_int_mask,
+ .int_clear = ambapp_gr740_int_clear,
+ .get_params = ambapp_gr740_get_params
+};
+
+struct drvmgr_drv_ops gr_cpci_gr740_ops =
+{
+ .init = {gr_cpci_gr740_init1, gr_cpci_gr740_init2, NULL, NULL},
+ .remove = NULL,
+ .info = NULL
+};
+
+struct pci_dev_id_match gr_cpci_gr740_ids[] =
+{
+ PCIID_DEVVEND(PCIID_VENDOR_GAISLER, PCIID_DEVICE_GR_CPCI_GR740),
+ PCIID_END_TABLE /* Mark end of table */
+};
+
+struct pci_drv_info gr_cpci_gr740_info =
+{
+ {
+ DRVMGR_OBJ_DRV, /* Driver */
+ NULL, /* Next driver */
+ NULL, /* Device list */
+ DRIVER_PCI_GAISLER_CPCI_GR740_ID, /* Driver ID */
+ "GR-CPCI-GR740", /* Driver Name */
+ DRVMGR_BUS_TYPE_PCI, /* Bus Type */
+ &gr_cpci_gr740_ops,
+ NULL, /* Funcs */
+ 0, /* No devices yet */
+ sizeof(struct gr_cpci_gr740_priv),
+ },
+ &gr_cpci_gr740_ids[0]
+};
+
+/* Driver resources configuration for the AMBA bus on the GR-CPCI-GR740 board.
+ * It is declared weak so that the user may override it from the project file,
+ * if the default settings are not enough.
+ *
+ * The configuration consists of an array of configuration pointers, each
+ * pointer determine the configuration of one GR-CPCI-GR740 board. Pointer
+ * zero is for board0, pointer 1 for board1 and so on.
+ *
+ * The array must end with a NULL pointer.
+ */
+struct drvmgr_bus_res *gr_cpci_gr740_resources[] __attribute__((weak)) =
+{
+ NULL
+};
+
+void gr_cpci_gr740_register_drv(void)
+{
+ DBG("Registering GR-CPCI-GR740 PCI driver\n");
+ drvmgr_drv_register(&gr_cpci_gr740_info.general);
+}
+
+void gr_cpci_gr740_isr(void *arg)
+{
+ struct gr_cpci_gr740_priv *priv = arg;
+ unsigned int status, tmp;
+ int irq, eirq;
+ tmp = status = priv->irq->ipend;
+
+ /* DBG("GR-CPCI-GR740: IRQ 0x%x\n",status); */
+
+ for(irq = 0; irq < 32; irq++) {
+ if (status & (1 << irq)) {
+ if (irq == priv->eirq) {
+ while ((eirq = priv->irq->intid[0] & 0x1f)) {
+ if ((eirq & 0x10) == 0)
+ continue;
+ genirq_doirq(priv->genirq, eirq);
+ priv->irq->iclear = (1 << eirq);
+ }
+ } else {
+ genirq_doirq(priv->genirq, irq);
+ }
+ priv->irq->iclear = (1 << irq);
+ status &= ~(1 << irq);
+ if ( status == 0 )
+ break;
+ }
+ }
+
+ /* ACK interrupt, this is because PCI is Level, so the IRQ Controller
+ * still drives the IRQ
+ */
+ if ( tmp )
+ drvmgr_interrupt_clear(priv->dev, 0);
+
+ DBG("GR-CPCI-GR740-IRQ: 0x%x\n", tmp);
+}
+
+static int gr_cpci_gr740_hw_init1(struct gr_cpci_gr740_priv *priv)
+{
+ int i;
+ uint32_t data;
+ unsigned int ctrl;
+ uint8_t tmp2;
+ struct ambapp_dev *tmp;
+ struct ambapp_ahb_info *ahb;
+ uint8_t cap_ptr;
+ pci_dev_t pcidev = priv->pcidev;
+ struct pci_dev_info *devinfo = priv->devinfo;
+ unsigned int cgmask, enabled;
+
+ /* Check capabilities list bit and read its pointer */
+ pci_cfg_r8(pcidev, PCIR_STATUS, &tmp2);
+ if (!((tmp2 >> 4) & 1)) {
+ /* Capabilities list not available which it should be in the GRPCI2 */
+ return -2;
+ }
+ pci_cfg_r8(pcidev, PCIR_CAP_PTR, &cap_ptr);
+
+ /* Set AHB address mappings for target PCI bars
+ * BAR0 maps to 0x00000000-0x07ffffff 128MB (SDRAM/DDR2 memory)
+ * BAR1 maps to 0xf0000000-0xf7ffffff 128MB (L2-Cache regs/diagnostics)
+ * BAR2 maps to 0xff800000-0xffffffff 8MB (PnP, I/O regs)
+ */
+ pci_cfg_w32(pcidev, cap_ptr+GRPCI2_BAR0_TO_AHB_MAP, 0x00000000);
+ pci_cfg_w32(pcidev, cap_ptr+GRPCI2_BAR1_TO_AHB_MAP, 0xf0000000);
+ pci_cfg_w32(pcidev, cap_ptr+GRPCI2_BAR2_TO_AHB_MAP, 0xff800000);
+
+ /* Set PCI bus to be big endian */
+ pci_cfg_r32(pcidev, cap_ptr+GRPCI2_PCI_CONFIG, &data);
+ data = data & 0xFFFFFFFE;
+ pci_cfg_w32(pcidev, cap_ptr+GRPCI2_PCI_CONFIG, data);
+
+#if 0
+ /* set parity error response */
+ pci_cfg_r32(pcidev, PCIR_COMMAND, &data);
+ pci_cfg_w32(pcidev, PCIR_COMMAND, (data|PCIM_CMD_PERRESPEN));
+#endif
+
+ /* Scan AMBA Plug&Play */
+
+ /* AMBA MAP bar0 (in gr740) ==> 0x00000000 (remote amba address) */
+ priv->amba_maps[0].size = devinfo->resources[0].size;
+ priv->amba_maps[0].local_adr = devinfo->resources[0].address;
+ priv->amba_maps[0].remote_adr = 0x00000000;
+
+ priv->amba_maps[1].size = devinfo->resources[1].size;
+ priv->amba_maps[1].local_adr = devinfo->resources[1].address;
+ priv->amba_maps[1].remote_adr = 0xf0000000;
+
+ priv->amba_maps[2].size = devinfo->resources[2].size;
+ priv->amba_maps[2].local_adr = devinfo->resources[2].address;
+ priv->amba_maps[2].remote_adr = 0xff800000;
+
+ /* Addresses not matching with map be untouched */
+ priv->amba_maps[3].size = 0xfffffff0;
+ priv->amba_maps[3].local_adr = 0;
+ priv->amba_maps[3].remote_adr = 0;
+
+ /* Mark end of table */
+ priv->amba_maps[4].size=0;
+
+ /* Start AMBA PnP scan at first AHB bus */
+ ambapp_scan(
+ &priv->abus,
+ devinfo->resources[2].address + 0x00700000,
+ NULL,
+ &priv->amba_maps[0]);
+
+ /* Initialize Frequency of AMBA bus */
+ ambapp_freq_init(&priv->abus, NULL, priv->amba_freq_hz);
+
+ /* Find IRQ controller, Clear all current IRQs */
+ tmp = (struct ambapp_dev *)ambapp_for_each(&priv->abus,
+ (OPTIONS_ALL|OPTIONS_APB_SLVS),
+ VENDOR_GAISLER, GAISLER_IRQMP,
+ ambapp_find_by_idx, NULL);
+ if ( !tmp ) {
+ return -4;
+ }
+ priv->irq = (struct irqmp_regs *)DEV_TO_APB(tmp)->start;
+ /* Set up GR-CPCI-GR740 irq controller
+ * Interrupts are routed from IRQCtrl0, we leave the configuration
+ * for the other CPUs, as the board's CPUs may be running something.
+ * We assume IRQCtrl has been set up properly, or at least the reset
+ * values shuold work with this code..
+ */
+ priv->irq->mask[0] = 0;
+ priv->irq->iforce = 0;
+ priv->irq->force[0] = 0;
+ priv->irq->ilevel = 0;
+ priv->irq->ipend = 0;
+ priv->irq->iclear = 0xffffffff;
+ priv->irq->ilevel = 0;
+ /* Get extended Interrupt controller IRQ number */
+ priv->eirq = (priv->irq->mpstat >> 16) & 0xf;
+
+ /* Find first Clock-Gating unit, enable/disable the requested cores */
+ tmp = (struct ambapp_dev *)ambapp_for_each(&priv->abus,
+ (OPTIONS_ALL|OPTIONS_APB_SLVS),
+ VENDOR_GAISLER, GAISLER_CLKGATE,
+ ambapp_find_by_idx, NULL);
+ if ( !tmp ) {
+ return -5;
+ }
+ priv->cg = (struct gr740_grcg_regs *)DEV_TO_APB(tmp)->start;
+ /* Do reset and enable sequence only if not already enabled */
+ if (priv->cg && ((enabled = priv->cg->enable) != priv->cg_en_mask)) {
+ /* First disable already enabled cores */
+ cgmask = ~priv->cg_en_mask & enabled;
+ if (cgmask) {
+ priv->cg->unlock = cgmask;
+ priv->cg->enable = enabled = ~cgmask & enabled;
+ priv->cg->unlock = 0;
+ }
+ /* Enable disabled cores */
+ cgmask = priv->cg_en_mask & ~enabled;
+ if (cgmask) {
+ priv->cg->unlock = cgmask;
+ priv->cg->reset |= cgmask;
+ priv->cg->enable = cgmask | enabled;
+ priv->cg->reset &= ~cgmask;
+ priv->cg->unlock = 0;
+ }
+ }
+
+ priv->bus_maps_down[0].name = "PCI BAR0 -> AMBA";
+ priv->bus_maps_down[0].size = priv->amba_maps[0].size;
+ priv->bus_maps_down[0].from_adr = (void *)priv->amba_maps[0].local_adr;
+ priv->bus_maps_down[0].to_adr = (void *)priv->amba_maps[0].remote_adr;
+ priv->bus_maps_down[1].name = "PCI BAR1 -> AMBA";
+ priv->bus_maps_down[1].size = priv->amba_maps[1].size;
+ priv->bus_maps_down[1].from_adr = (void *)priv->amba_maps[1].local_adr;
+ priv->bus_maps_down[1].to_adr = (void *)priv->amba_maps[1].remote_adr;
+ priv->bus_maps_down[2].name = "PCI BAR2 -> AMBA";
+ priv->bus_maps_down[2].size = priv->amba_maps[2].size;
+ priv->bus_maps_down[2].from_adr = (void *)priv->amba_maps[2].local_adr;
+ priv->bus_maps_down[2].to_adr = (void *)priv->amba_maps[2].remote_adr;
+ priv->bus_maps_down[3].size = 0;
+
+ /* Find GRPCI2 controller AHB Slave interface */
+ tmp = (struct ambapp_dev *)ambapp_for_each(&priv->abus,
+ (OPTIONS_ALL|OPTIONS_AHB_SLVS),
+ VENDOR_GAISLER, GAISLER_GRPCI2,
+ ambapp_find_by_idx, NULL);
+ if ( !tmp ) {
+ return -6;
+ }
+ ahb = (struct ambapp_ahb_info *)tmp->devinfo;
+ priv->bus_maps_up[0].name = "AMBA GRPCI2 Window";
+ priv->bus_maps_up[0].size = ahb->mask[0]; /* AMBA->PCI Window on GR-CPCI-GR740 board */
+ priv->bus_maps_up[0].from_adr = (void *)ahb->start[0];
+ priv->bus_maps_up[0].to_adr = (void *)
+ (priv->ahbmst2pci_map & ~(ahb->mask[0]-1));
+ priv->bus_maps_up[1].size = 0;
+
+ /* Find GRPCI2 controller APB Slave interface */
+ tmp = (struct ambapp_dev *)ambapp_for_each(&priv->abus,
+ (OPTIONS_ALL|OPTIONS_APB_SLVS),
+ VENDOR_GAISLER, GAISLER_GRPCI2,
+ ambapp_find_by_idx, NULL);
+ if ( !tmp ) {
+ return -7;
+ }
+ priv->grpci2 = (struct grpci2_regs *)
+ ((struct ambapp_apb_info *)tmp->devinfo)->start;
+
+ /* Set AHB to PCI mapping for all AMBA AHB masters */
+ for(i = 0; i < 16; i++) {
+ priv->grpci2->ahbmst_map[i] = priv->ahbmst2pci_map &
+ ~(ahb->mask[0]-1);
+ }
+
+ /* Make sure dirq(0) sampling is enabled */
+ ctrl = priv->grpci2->ctrl;
+ ctrl = (ctrl & 0xFFFFFF0F) | (1 << 4);
+ priv->grpci2->ctrl = ctrl;
+
+ /* Successfully registered the GR740 board */
+ return 0;
+}
+
+static int gr_cpci_gr740_hw_init2(struct gr_cpci_gr740_priv *priv)
+{
+ /* Enable DMA by enabling PCI target as master */
+ pci_master_enable(priv->pcidev);
+
+ return DRVMGR_OK;
+}
+
+/* Called when a PCI target is found with the PCI device and vendor ID
+ * given in gr_cpci_gr740_ids[].
+ */
+int gr_cpci_gr740_init1(struct drvmgr_dev *dev)
+{
+ struct gr_cpci_gr740_priv *priv;
+ struct pci_dev_info *devinfo;
+ int status, i;
+ union drvmgr_key_value *value;
+ int resources_cnt;
+
+ priv = dev->priv;
+ if (!priv)
+ return DRVMGR_NOMEM;
+
+ memset(priv, 0, sizeof(*priv));
+ dev->priv = priv;
+ priv->dev = dev;
+
+ /* Determine number of configurations */
+ resources_cnt = get_resarray_count(gr_cpci_gr740_resources);
+
+ /* Generate Device prefix */
+
+ strcpy(priv->prefix, "/dev/gr7400");
+ priv->prefix[10] += dev->minor_drv;
+ mkdir(priv->prefix, S_IRWXU | S_IRWXG | S_IRWXO);
+ priv->prefix[11] = '/';
+ priv->prefix[12] = '\0';
+
+ priv->devinfo = devinfo = (struct pci_dev_info *)dev->businfo;
+ priv->pcidev = devinfo->pcidev;
+ printf("\n\n--- GR-CPCI-GR740[%d] ---\n", dev->minor_drv);
+ printf(" PCI BUS: 0x%x, SLOT: 0x%x, FUNCTION: 0x%x\n",
+ PCI_DEV_EXPAND(priv->pcidev));
+ printf(" PCI VENDOR: 0x%04x, DEVICE: 0x%04x\n",
+ devinfo->id.vendor, devinfo->id.device);
+ for (i = 0; i < 3; i++) {
+ printf(" PCI BAR[%d]: 0x%08lx - 0x%08lx\n",
+ i, devinfo->resources[i].address,
+ devinfo->resources[i].address +
+ (devinfo->resources[i].size - 1));
+ /* all neccessary space assigned to GR-CPCI-GR740 target? */
+ if (devinfo->resources[i].size == 0)
+ return DRVMGR_ENORES;
+ }
+ printf(" IRQ: %d\n\n\n", devinfo->irq);
+
+ /* Let user override which PCI address the AHB masters of the
+ * GR740 board access when doing DMA to HOST RAM. The AHB masters
+ * access the PCI Window of the AMBA bus, the MSB 2-bits of that address
+ * is translated according this config option before the address goes
+ * out on the PCI bus.
+ *
+ * Only the 2 MSB bits have an effect.
+ */
+ value = drvmgr_dev_key_get(priv->dev, "ahbmst2pci", DRVMGR_KT_INT);
+ if (value)
+ priv->ahbmst2pci_map = value->i;
+ else
+ priv->ahbmst2pci_map = AHBMST2PCIADR; /* default */
+
+ /* Let user override the default AMBA system frequency of the
+ * CPU-bus of the remote GR-CPCI-GR740. Default is 250MHz.
+ */
+ value = drvmgr_dev_key_get(priv->dev, "ambaFreq", DRVMGR_KT_INT);
+ if (value)
+ priv->amba_freq_hz = value->i;
+ else
+ priv->amba_freq_hz = 250000000; /* default */
+
+ /* Let user determine clock-gating unit configuration. The default
+ * is to turn all cores on (disable gating). PCI is always turned ON.
+ */
+ value = drvmgr_dev_key_get(priv->dev, "cgEnMask", DRVMGR_KT_INT);
+ if (value)
+ priv->cg_en_mask = (value->i & CG_MASK) | 0x08;
+ else
+ priv->cg_en_mask = CG_MASK; /* default all ON */
+
+ priv->genirq = genirq_init(32);
+ if (priv->genirq == NULL)
+ return DRVMGR_FAIL;
+
+ if ((status = gr_cpci_gr740_hw_init1(priv)) != 0) {
+ genirq_destroy(priv->genirq);
+ printf(" Failed to initialize GR-CPCI-GR740 HW: %d\n", status);
+ return DRVMGR_FAIL;
+ }
+
+ /* Init amba bus */
+ priv->config.abus = &priv->abus;
+ priv->config.ops = &ambapp_gr740_ops;
+ priv->config.maps_up = &priv->bus_maps_up[0];
+ priv->config.maps_down = &priv->bus_maps_down[0];
+ if ( priv->dev->minor_drv < resources_cnt ) {
+ priv->config.resources = gr_cpci_gr740_resources[priv->dev->minor_drv];
+ } else {
+ priv->config.resources = NULL;
+ }
+
+ /* Create and register AMBA PnP bus. */
+ return ambapp_bus_register(dev, &priv->config);
+}
+
+int gr_cpci_gr740_init2(struct drvmgr_dev *dev)
+{
+ struct gr_cpci_gr740_priv *priv = dev->priv;
+
+ /* Clear any old interrupt requests */
+ drvmgr_interrupt_clear(dev, 0);
+
+ /* Enable System IRQ so that GR-CPCI-GR740 PCI target interrupt
+ * goes through.
+ *
+ * It is important to enable it in stage init2. If interrupts were
+ * enabled in init1 this might hang the system when more than one
+ * PCI board is connected, this is because PCI interrupts might
+ * be shared and PCI board 2 have not initialized and
+ * might therefore drive interrupt already when entering init1().
+ */
+ drvmgr_interrupt_register(
+ dev,
+ 0,
+ "gr_cpci_gr740",
+ gr_cpci_gr740_isr,
+ (void *)priv);
+
+ return gr_cpci_gr740_hw_init2(priv);
+}
+
+int ambapp_gr740_int_register(
+ struct drvmgr_dev *dev,
+ int irq,
+ const char *info,
+ drvmgr_isr handler,
+ void *arg)
+{
+ struct gr_cpci_gr740_priv *priv = dev->parent->dev->priv;
+ rtems_interrupt_level level;
+ int status;
+
+ rtems_interrupt_disable(level);
+
+ status = genirq_register(priv->genirq, irq, handler, arg);
+ if (status == 0) {
+ /* Clear IRQ for first registered handler */
+ priv->irq->iclear = (1<<irq);
+ } else if (status == 1)
+ status = 0;
+
+ if (status != 0) {
+ rtems_interrupt_enable(level);
+ return DRVMGR_FAIL;
+ }
+
+ status = genirq_enable(priv->genirq, irq, handler, arg);
+ if ( status == 0 ) {
+ /* Enable IRQ for first enabled handler only */
+ priv->irq->mask[0] |= (1<<irq); /* unmask interrupt source */
+ } else if ( status == 1 )
+ status = 0;
+
+ rtems_interrupt_enable(level);
+
+ return status;
+}
+
+int ambapp_gr740_int_unregister(
+ struct drvmgr_dev *dev,
+ int irq,
+ drvmgr_isr isr,
+ void *arg)
+{
+ struct gr_cpci_gr740_priv *priv = dev->parent->dev->priv;
+ rtems_interrupt_level level;
+ int status;
+
+ rtems_interrupt_disable(level);
+
+ status = genirq_disable(priv->genirq, irq, isr, arg);
+ if ( status == 0 ) {
+ /* Disable IRQ only when no enabled handler exists */
+ priv->irq->mask[0] &= ~(1<<irq); /* mask interrupt source */
+ }
+
+ status = genirq_unregister(priv->genirq, irq, isr, arg);
+ if ( status != 0 )
+ status = DRVMGR_FAIL;
+
+ rtems_interrupt_enable(level);
+
+ return status;
+}
+
+int ambapp_gr740_int_unmask(
+ struct drvmgr_dev *dev,
+ int irq)
+{
+ struct gr_cpci_gr740_priv *priv = dev->parent->dev->priv;
+ rtems_interrupt_level level;
+
+ DBG("GR740 IRQ %d: unmask\n", irq);
+
+ if ( genirq_check(priv->genirq, irq) )
+ return DRVMGR_EINVAL;
+
+ rtems_interrupt_disable(level);
+
+ /* Enable IRQ for first enabled handler only */
+ priv->irq->mask[0] |= (1<<irq); /* unmask interrupt source */
+
+ rtems_interrupt_enable(level);
+
+ return DRVMGR_OK;
+}
+
+int ambapp_gr740_int_mask(
+ struct drvmgr_dev *dev,
+ int irq)
+{
+ struct gr_cpci_gr740_priv *priv = dev->parent->dev->priv;
+ rtems_interrupt_level level;
+
+ DBG("GR740 IRQ %d: mask\n", irq);
+
+ if ( genirq_check(priv->genirq, irq) )
+ return DRVMGR_EINVAL;
+
+ rtems_interrupt_disable(level);
+
+ /* Disable/mask IRQ */
+ priv->irq->mask[0] &= ~(1<<irq); /* mask interrupt source */
+
+ rtems_interrupt_enable(level);
+
+ return DRVMGR_OK;
+}
+
+int ambapp_gr740_int_clear(
+ struct drvmgr_dev *dev,
+ int irq)
+{
+ struct gr_cpci_gr740_priv *priv = dev->parent->dev->priv;
+
+ if ( genirq_check(priv->genirq, irq) )
+ return DRVMGR_EINVAL;
+
+ priv->irq->iclear = (1<<irq);
+
+ return DRVMGR_OK;
+}
+
+int ambapp_gr740_get_params(struct drvmgr_dev *dev, struct drvmgr_bus_params *params)
+{
+ struct gr_cpci_gr740_priv *priv = dev->parent->dev->priv;
+
+ /* Device name prefix pointer, skip /dev */
+ params->dev_prefix = &priv->prefix[5];
+
+ return 0;
+}
+
+void gr_cpci_gr740_print_dev(struct drvmgr_dev *dev, int options)
+{
+ struct gr_cpci_gr740_priv *priv = dev->priv;
+ struct pci_dev_info *devinfo = priv->devinfo;
+ uint32_t bar0, bar0_size;
+
+ /* Print */
+ printf("--- GR-CPCI-GR740 [bus 0x%x, dev 0x%x, fun 0x%x] ---\n",
+ PCI_DEV_EXPAND(priv->pcidev));
+
+ bar0 = devinfo->resources[0].address;
+ bar0_size = devinfo->resources[0].size;
+ printf(" PCI BAR[0]: 0x%lx - 0x%lx\n", bar0, bar0 + bar0_size - 1);
+ printf(" IRQ REGS: 0x%x\n", (unsigned int)priv->irq);
+ printf(" IRQ: %d\n", devinfo->irq);
+ printf(" PCI REVISION: %d\n", devinfo->rev);
+ printf(" FREQ: %d Hz\n", priv->amba_freq_hz);
+ printf(" IMASK: 0x%08x\n", priv->irq->mask[0]);
+ printf(" IPEND: 0x%08x\n", priv->irq->ipend);
+
+ /* Print amba config */
+ if (options & GR_CPCI_GR740_OPTIONS_AMBA)
+ ambapp_print(&priv->abus, 10);
+}
+
+void gr_cpci_gr740_print(int options)
+{
+ struct pci_drv_info *drv = &gr_cpci_gr740_info;
+ struct drvmgr_dev *dev;
+
+ dev = drv->general.dev;
+ while(dev) {
+ gr_cpci_gr740_print_dev(dev, options);
+ dev = dev->next_in_drv;
+ }
+}
diff --git a/cpukit/libdrvmgr/drvmgr_confdefs.h b/cpukit/libdrvmgr/drvmgr_confdefs.h
index 22c7a90..7692650 100644
--- a/cpukit/libdrvmgr/drvmgr_confdefs.h
+++ b/cpukit/libdrvmgr/drvmgr_confdefs.h
@@ -72,6 +72,7 @@ extern void gr701_register_drv(void);
extern void gr_tmtc_1553_register_drv(void);
extern void gr_rasta_spw_router_register_drv(void);
extern void gr_cpci_leon4_n2x_register_drv(void);
+extern void gr_cpci_gr740_register_drv(void);
/* CONFIGURE DRIVER MANAGER */
@@ -192,6 +193,9 @@ drvmgr_drv_reg_func drvmgr_drivers[] = {
#ifdef CONFIGURE_DRIVER_PCI_GR_LEON4_N2X
gr_cpci_leon4_n2x_register_drv,
#endif
+#ifdef CONFIGURE_DRIVER_PCI_GR_CPCI_GR740
+ gr_cpci_gr740_register_drv,
+#endif
/* Macros for adding custom drivers without needing to recompile
diff --git a/cpukit/libpci/pci/ids_extra.h b/cpukit/libpci/pci/ids_extra.h
index a7d2bc5..0b85fe2 100644
--- a/cpukit/libpci/pci/ids_extra.h
+++ b/cpukit/libpci/pci/ids_extra.h
@@ -19,3 +19,4 @@
#define PCIID_DEVICE_GR_RASTA_SPW_RTR 0x0062 /* GR-RASTA-SPW-ROUTER */
#define PCIID_DEVICE_GR_LEON4_N2X 0x0061 /* GR-CPCI-LEON4-N2X */
#define PCIID_DEVICE_GR_NGMP_PROTO 0x0064 /* GR-NGMP_PROTO */
+#define PCIID_DEVICE_GR_CPCI_GR740 0x0740 /* GR-CPCI-GR740 */
diff --git a/cpukit/libpci/pci_bus.h b/cpukit/libpci/pci_bus.h
index 7a4e253..b426010 100644
--- a/cpukit/libpci/pci_bus.h
+++ b/cpukit/libpci/pci_bus.h
@@ -47,6 +47,7 @@ extern "C" {
#define DRIVER_PCI_GAISLER_TMTC_1553_ID DRIVER_PCI_ID(PCIID_VENDOR_GAISLER, PCIID_DEVICE_GR_TMTC_1553)
#define DRIVER_PCI_GAISLER_RASTA_SPW_ROUTER_ID DRIVER_PCI_ID(PCIID_VENDOR_GAISLER, PCIID_DEVICE_GR_RASTA_SPW_RTR)
#define DRIVER_PCI_GAISLER_LEON4_N2X_ID DRIVER_PCI_ID(PCIID_VENDOR_GAISLER, PCIID_DEVICE_GR_LEON4_N2X)
+#define DRIVER_PCI_GAISLER_CPCI_GR740_ID DRIVER_PCI_ID(PCIID_VENDOR_GAISLER, PCIID_DEVICE_GR_CPCI_GR740)
struct pci_dev_id {
uint16_t vendor;
--
2.7.4
More information about the devel
mailing list