summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Hellstrom <daniel@gaisler.com>2013-12-20 14:06:37 +0100
committerDaniel Hellstrom <daniel@gaisler.com>2013-12-22 11:06:05 +0100
commit119023e8c2268ab44129d1b9f34dc66699beea61 (patch)
tree2d31429b7b0d085b43d340748354d52798775b5e
parent32b900f134dd86b470bc6226bb603c09bed9deef (diff)
SPWTDP: added SpW Time Distribution Protocol driverrcc-v1.2.14
This driver supports mainly device discovery and interrupt handling.
-rw-r--r--c/src/lib/libbsp/sparc/Makefile.am2
-rw-r--r--c/src/lib/libbsp/sparc/leon2/Makefile.am2
-rw-r--r--c/src/lib/libbsp/sparc/leon2/preinstall.am4
-rw-r--r--c/src/lib/libbsp/sparc/leon3/Makefile.am2
-rw-r--r--c/src/lib/libbsp/sparc/leon3/preinstall.am4
-rw-r--r--c/src/lib/libbsp/sparc/shared/include/spwtdp.h114
-rw-r--r--c/src/lib/libbsp/sparc/shared/time/spwtdp.c252
7 files changed, 380 insertions, 0 deletions
diff --git a/c/src/lib/libbsp/sparc/Makefile.am b/c/src/lib/libbsp/sparc/Makefile.am
index 12aeb8d194..cbf7a08ddc 100644
--- a/c/src/lib/libbsp/sparc/Makefile.am
+++ b/c/src/lib/libbsp/sparc/Makefile.am
@@ -122,8 +122,10 @@ EXTRA_DIST += shared/include/spictrl.h
# TIME
EXTRA_DIST += shared/time/spwcuc.c
+EXTRA_DIST += shared/time/spwtdp.c
EXTRA_DIST += shared/time/grctm.c
EXTRA_DIST += shared/include/spwcuc.h
+EXTRA_DIST += shared/include/spwtdp.h
EXTRA_DIST += shared/include/grctm.h
# GPIO
diff --git a/c/src/lib/libbsp/sparc/leon2/Makefile.am b/c/src/lib/libbsp/sparc/leon2/Makefile.am
index 94133d6dc1..2fedddc83e 100644
--- a/c/src/lib/libbsp/sparc/leon2/Makefile.am
+++ b/c/src/lib/libbsp/sparc/leon2/Makefile.am
@@ -155,8 +155,10 @@ libbsp_a_SOURCES += ../../sparc/shared/spi/spictrl.c
# TIME
include_HEADERS += ../../sparc/shared/include/spwcuc.h
+include_HEADERS += ../../sparc/shared/include/spwtdp.h
include_HEADERS += ../../sparc/shared/include/grctm.h
libbsp_a_SOURCES += ../../sparc/shared/time/spwcuc.c
+libbsp_a_SOURCES += ../../sparc/shared/time/spwtdp.c
libbsp_a_SOURCES += ../../sparc/shared/time/grctm.c
# GPIO
diff --git a/c/src/lib/libbsp/sparc/leon2/preinstall.am b/c/src/lib/libbsp/sparc/leon2/preinstall.am
index d9c77cddeb..61ff4802c8 100644
--- a/c/src/lib/libbsp/sparc/leon2/preinstall.am
+++ b/c/src/lib/libbsp/sparc/leon2/preinstall.am
@@ -205,6 +205,10 @@ $(PROJECT_INCLUDE)/spwcuc.h: ../../sparc/shared/include/spwcuc.h $(PROJECT_INCLU
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/spwcuc.h
PREINSTALL_FILES += $(PROJECT_INCLUDE)/spwcuc.h
+$(PROJECT_INCLUDE)/spwtdp.h: ../../sparc/shared/include/spwtdp.h $(PROJECT_INCLUDE)/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/spwtdp.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/spwtdp.h
+
$(PROJECT_INCLUDE)/grctm.h: ../../sparc/shared/include/grctm.h $(PROJECT_INCLUDE)/$(dirstamp)
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/grctm.h
PREINSTALL_FILES += $(PROJECT_INCLUDE)/grctm.h
diff --git a/c/src/lib/libbsp/sparc/leon3/Makefile.am b/c/src/lib/libbsp/sparc/leon3/Makefile.am
index 617f7bb5d1..d71200f738 100644
--- a/c/src/lib/libbsp/sparc/leon3/Makefile.am
+++ b/c/src/lib/libbsp/sparc/leon3/Makefile.am
@@ -171,8 +171,10 @@ libbsp_a_SOURCES += ../../sparc/shared/spi/spictrl.c
# TIME
include_HEADERS += ../../sparc/shared/include/spwcuc.h
+include_HEADERS += ../../sparc/shared/include/spwtdp.h
include_HEADERS += ../../sparc/shared/include/grctm.h
libbsp_a_SOURCES += ../../sparc/shared/time/spwcuc.c
+libbsp_a_SOURCES += ../../sparc/shared/time/spwtdp.c
libbsp_a_SOURCES += ../../sparc/shared/time/grctm.c
# GPIO
diff --git a/c/src/lib/libbsp/sparc/leon3/preinstall.am b/c/src/lib/libbsp/sparc/leon3/preinstall.am
index 8bc841b5c6..c4bad50ba1 100644
--- a/c/src/lib/libbsp/sparc/leon3/preinstall.am
+++ b/c/src/lib/libbsp/sparc/leon3/preinstall.am
@@ -225,6 +225,10 @@ $(PROJECT_INCLUDE)/spwcuc.h: ../../sparc/shared/include/spwcuc.h $(PROJECT_INCLU
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/spwcuc.h
PREINSTALL_FILES += $(PROJECT_INCLUDE)/spwcuc.h
+$(PROJECT_INCLUDE)/spwtdp.h: ../../sparc/shared/include/spwtdp.h $(PROJECT_INCLUDE)/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/spwtdp.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/spwtdp.h
+
$(PROJECT_INCLUDE)/grctm.h: ../../sparc/shared/include/grctm.h $(PROJECT_INCLUDE)/$(dirstamp)
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/grctm.h
PREINSTALL_FILES += $(PROJECT_INCLUDE)/grctm.h
diff --git a/c/src/lib/libbsp/sparc/shared/include/spwtdp.h b/c/src/lib/libbsp/sparc/shared/include/spwtdp.h
new file mode 100644
index 0000000000..31ef0cbf12
--- /dev/null
+++ b/c/src/lib/libbsp/sparc/shared/include/spwtdp.h
@@ -0,0 +1,114 @@
+/* SPWTDP - SpaceWire Time Distribution Protocol. The driver provides
+ * device discovery and interrupt management.
+ *
+ * COPYRIGHT (c) 2013.
+ * Aeroflex Gaisler AB
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ */
+
+#ifndef __SPWTDP_H__
+#define __SPWTDP_H__
+
+#define SPWTDP_IRQ_SYNC 0x01
+#define SPWTDP_IRQ_TICKRX_ERR 0x02
+#define SPWTDP_IRQ_TICKRX 0x04
+#define SPWTDP_IRQ_TIME_MSG_TX 0x08
+#define SPWTDP_IRQ_TICKTX 0x10
+#define SPWTDP_IRQ_RX 0x20
+#define SPWTDP_IRQ_TX 0x40
+
+/* SPWTDP Register layout */
+struct spwtdp_regs {
+ volatile unsigned int conf[4]; /* 00 */
+ volatile unsigned int stat[4]; /* 10 */
+ volatile unsigned int cmd_ctrl; /* 20 */
+ volatile unsigned int cmd_et[5]; /* 24 */
+ volatile unsigned int resv1[2]; /* 38 */
+ volatile unsigned int dat_ctrl; /* 40 */
+ volatile unsigned int dat_et[5]; /* 44 */
+ volatile unsigned int resv2[2]; /* 58 */
+ volatile unsigned int ts_tx_ctrl; /* 60 */
+ volatile unsigned int ts_tx_et[5]; /* 64 */
+ volatile unsigned int resv3[2]; /* 78 */
+ volatile unsigned int ts_rx_ctrl; /* 80 */
+ volatile unsigned int ts_rx_et[5]; /* 84 */
+ volatile unsigned int resv4[2]; /* 98 */
+ volatile unsigned int lat_ctrl; /* A0 */
+ volatile unsigned int lat_et[5]; /* A4 */
+ volatile unsigned int resv5[2]; /* B8 */
+ volatile unsigned int ien; /* C0 */
+ volatile unsigned int ists; /* C4 */
+};
+
+/* SPWTDP Statistics gathered by driver */
+struct spwtdp_stats {
+
+ /* IRQ Stats */
+ unsigned int nirqs;
+ unsigned int tx;
+ unsigned int rx;
+ unsigned int tick_tx;
+ unsigned int time_msg_tx;
+ unsigned int tick_rx;
+ unsigned int tick_rx_err;
+ unsigned int sync;
+};
+
+/* Function ISR callback prototype
+ *
+ * ists - Interrupt STatus register of the SPWTDP core read by ISR
+ * data - Custom data provided by user
+ */
+typedef void (*spwtdp_isr_t)(unsigned int ists, void *data);
+
+/* Open a SPWTDP device by minor number. A SPWTDP device can only by opened
+ * once. The handle returned must be used as the input parameter 'spwtdp' in
+ * the rest of the calls in the function interface.
+ */
+extern void *spwtdp_open(int minor);
+
+/* Close a previously opened SPWTDP device */
+extern void spwtdp_close(void *spwtdp);
+
+/* Reset SPWTDP Core */
+extern int spwtdp_reset(void *spwtdp);
+
+/* Enable Interrupts at Interrupt controller */
+extern void spwtdp_int_enable(void *spwtdp);
+
+/* Disable Interrupts at Interrupt controller */
+extern void spwtdp_int_disable(void *spwtdp);
+
+/* Clear Statistics gathered by the driver */
+extern void spwtdp_clr_stats(void *spwtdp);
+
+/* Get Statistics gathered by the driver. The statistics are stored into
+ * the location pointed to by 'stats'.
+ */
+extern void spwtdp_get_stats(void *spwtdp, struct spwtdp_stats *stats);
+
+/* Register an Interrupt handler and custom data, the function call is
+ * removed by setting func to NULL.
+ *
+ * The driver's interrupt handler is installed on open(), however the user
+ * callback called from the driver's ISR is installed using this function.
+ */
+extern void spwtdp_int_register(void *spwtdp, spwtdp_isr_t func, void *data);
+
+/* Clear interrupts */
+extern void spwtdp_clear_irqs(void *spwtdp, int irqs);
+
+/* Enable interrupts */
+extern void spwtdp_enable_irqs(void *spwtdp, int irqs);
+
+/* Get Register */
+extern struct spwtdp_regs *spwtdp_get_regs(void *spwtdp);
+
+/* Register the SPWTDP Driver to the Driver Manager */
+extern void spwtdp_register(void);
+
+#endif
diff --git a/c/src/lib/libbsp/sparc/shared/time/spwtdp.c b/c/src/lib/libbsp/sparc/shared/time/spwtdp.c
new file mode 100644
index 0000000000..4b22346ab0
--- /dev/null
+++ b/c/src/lib/libbsp/sparc/shared/time/spwtdp.c
@@ -0,0 +1,252 @@
+/* SPWTDP - SpaceWire Time Distribution Protocol. The driver provides
+ * device discovery and interrupt management.
+ *
+ * COPYRIGHT (c) 2009.
+ * Aeroflex Gaisler AB
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ */
+
+#include <drvmgr/drvmgr.h>
+#include <drvmgr/ambapp_bus.h>
+#include <stdlib.h>
+
+#include <spwtdp.h>
+
+#define DRIVER_AMBAPP_GAISLER_SPWTDP_ID DRIVER_AMBAPP_ID(VENDOR_GAISLER, GAISLER_SPWTDP)
+
+/* Private structure of SPWTDP driver. */
+struct spwtdp_priv {
+ struct drvmgr_dev *dev;
+ struct spwtdp_regs *regs;
+ int open;
+
+ spwtdp_isr_t user_isr;
+ void *user_isr_arg;
+
+ struct spwtdp_stats stats;
+};
+
+void spwtdp_isr(void *data);
+
+struct amba_drv_info spwtdp_drv_info;
+
+/* Hardware Reset of SPWTDP */
+int spwtdp_hw_reset(struct spwtdp_priv *priv)
+{
+ struct spwtdp_regs *r = priv->regs;
+ int i = 1000;
+
+ r->conf[0] = 1;
+
+ while ((r->conf[0] & 1) && i > 0) {
+ i--;
+ }
+
+ spwtdp_clear_irqs(priv, -1);
+
+ return i ? 0 : -1;
+}
+
+int spwtdp_reset(void *spwtdp)
+{
+ struct spwtdp_priv *priv = (struct spwtdp_priv *)spwtdp;
+
+ return spwtdp_hw_reset(priv);
+}
+
+void *spwtdp_open(int minor)
+{
+ struct spwtdp_priv *priv;
+ struct drvmgr_dev *dev;
+
+ /* Get Device from Minor */
+ if ( drvmgr_get_dev(&spwtdp_drv_info.general, minor, &dev) ) {
+ return NULL;
+ }
+
+ priv = dev->priv;
+ if ( (priv == NULL) || priv->open )
+ return NULL;
+
+ /* Set initial state of software */
+ priv->open = 1;
+
+ /* Clear Statistics */
+ spwtdp_clr_stats(priv);
+ priv->user_isr = NULL;
+ priv->user_isr_arg = NULL;
+
+ return priv;
+}
+
+void spwtdp_close(void *spwtdp)
+{
+ struct spwtdp_priv *priv = (struct spwtdp_priv *)spwtdp;
+
+ if ( priv->open == 0 )
+ return;
+
+ /* Reset Hardware */
+ spwtdp_hw_reset(priv);
+
+ priv->open = 0;
+}
+
+void spwtdp_int_enable(void *spwtdp)
+{
+ struct spwtdp_priv *priv = (struct spwtdp_priv *)spwtdp;
+
+ /* Register and Enable Interrupt at Interrupt controller */
+ drvmgr_interrupt_register(priv->dev, 0, "spwtdp", spwtdp_isr, priv);
+}
+
+void spwtdp_int_disable(void *spwtdp)
+{
+ struct spwtdp_priv *priv = (struct spwtdp_priv *)spwtdp;
+
+ /* Enable Interrupt at Interrupt controller */
+ drvmgr_interrupt_unregister(priv->dev, 0, spwtdp_isr, priv);
+}
+
+void spwtdp_clr_stats(void *spwtdp)
+{
+ struct spwtdp_priv *priv = (struct spwtdp_priv *)spwtdp;
+
+ memset(&priv->stats, 0, sizeof(priv->stats));
+}
+
+void spwtdp_get_stats(void *spwtdp, struct spwtdp_stats *stats)
+{
+ struct spwtdp_priv *priv = (struct spwtdp_priv *)spwtdp;
+
+ memcpy(stats, &priv->stats, sizeof(priv->stats));
+}
+
+/* Clear interrupts */
+void spwtdp_clear_irqs(void *spwtdp, int irqs)
+{
+ struct spwtdp_priv *priv = (struct spwtdp_priv *)spwtdp;
+
+ priv->regs->ists = irqs;
+}
+
+/* Enable interrupts */
+void spwtdp_enable_irqs(void *spwtdp, int irqs)
+{
+ struct spwtdp_priv *priv = (struct spwtdp_priv *)spwtdp;
+
+ priv->regs->ien = irqs;
+}
+
+struct spwtdp_regs *spwtdp_get_regs(void *spwtdp)
+{
+ struct spwtdp_priv *priv = (struct spwtdp_priv *)spwtdp;
+
+ return priv->regs;
+}
+
+void spwtdp_int_register(void *spwtdp, spwtdp_isr_t func, void *data)
+{
+ struct spwtdp_priv *priv = (struct spwtdp_priv *)spwtdp;
+
+ priv->user_isr = func;
+ priv->user_isr_arg = data;
+}
+
+void spwtdp_isr(void *data)
+{
+ struct spwtdp_priv *priv = data;
+ struct spwtdp_stats *stats = &priv->stats;
+ unsigned int ists = priv->regs->ists;
+
+ stats->nirqs++;
+
+ if (ists & SPWTDP_IRQ_TX)
+ stats->tx++;
+ if (ists & SPWTDP_IRQ_RX)
+ stats->rx++;
+ if (ists & SPWTDP_IRQ_TICKTX)
+ stats->tick_tx++;
+ if (ists & SPWTDP_IRQ_TIME_MSG_TX)
+ stats->time_msg_tx++;
+ if (ists & SPWTDP_IRQ_TICKRX)
+ stats->tick_rx++;
+ if (ists & SPWTDP_IRQ_TICKRX_ERR)
+ stats->tick_rx_err++;
+ if (ists & SPWTDP_IRQ_SYNC)
+ stats->sync++;
+
+ /* Let user Handle Interrupt */
+ if (priv->user_isr)
+ priv->user_isr(ists, priv->user_isr_arg);
+}
+
+/*** INTERFACE TO DRIVER MANAGER ***/
+
+int spwtdp_init2(struct drvmgr_dev *dev)
+{
+ struct amba_dev_info *ambadev;
+ struct ambapp_core *pnpinfo;
+ struct spwtdp_priv *priv;
+ struct spwtdp_regs *regs;
+
+ priv = dev->priv;
+ if (priv == NULL)
+ return DRVMGR_NOMEM;
+ memset(priv, 0, sizeof(*priv));
+ priv->dev = dev;
+
+ /* Get device information from AMBA PnP information */
+ ambadev = (struct amba_dev_info *)dev->businfo;
+ if ( ambadev == NULL ) {
+ return DRVMGR_ENORES;
+ }
+ pnpinfo = &ambadev->info;
+ regs = (struct spwtdp_regs *)pnpinfo->apb_slv->start;
+
+ priv->regs = regs;
+
+ spwtdp_hw_reset(priv);
+
+ return DRVMGR_OK;
+}
+
+struct drvmgr_drv_ops spwtdp_ops =
+{
+ {NULL, spwtdp_init2, NULL, NULL},
+ NULL,
+ NULL
+};
+
+struct amba_dev_id spwtdp_ids[] =
+{
+ {VENDOR_GAISLER, GAISLER_SPWTDP},
+ {0, 0} /* Mark end of table */
+};
+
+struct amba_drv_info spwtdp_drv_info =
+{
+ {
+ DRVMGR_OBJ_DRV, /* Driver */
+ NULL, /* Next driver */
+ NULL, /* Device list */
+ DRIVER_AMBAPP_GAISLER_SPWTDP_ID,/* Driver ID */
+ "SPWTDP_DRV", /* Driver Name */
+ DRVMGR_BUS_TYPE_AMBAPP, /* Bus Type */
+ &spwtdp_ops,
+ NULL, /* Funcs */
+ 0, /* No devices yet */
+ sizeof(struct spwtdp_priv), /* Let DrvMgr allocate priv */
+ },
+ &spwtdp_ids[0]
+};
+
+/* Register the SPWTDP Driver */
+void spwtdp_register(void)
+{
+ drvmgr_drv_register(&spwtdp_drv_info.general);
+}