summaryrefslogtreecommitdiffstats
path: root/c/src/lib/libbsp/sparc/shared/time
diff options
context:
space:
mode:
authorDaniel Hellstrom <daniel@gaisler.com>2015-02-23 13:02:39 +0100
committerDaniel Hellstrom <daniel@gaisler.com>2015-04-17 01:10:17 +0200
commit3bb41226e0941b86d58ecb97f7d292677de573c8 (patch)
tree907aa270343f7c6d1bc08bf73288fb9b10da6197 /c/src/lib/libbsp/sparc/shared/time
parentLEON: added network device configuration helper function (diff)
downloadrtems-3bb41226e0941b86d58ecb97f7d292677de573c8.tar.bz2
LEON: added new drivers to the LEON2/LEON3 BSPs
Most drivers use the Driver Manager for device probing, they work on AMBA-over-PCI systems if PCI is big-endian. New APIs: * GPIO Library, interfaced to GRGPIO * GENIRQ, Generic interrupt service implementation helper New GRLIB Drivers: * ACTEL 1553 RT, user interface is similar to 1553 BRM driver * GR1553 (1553 BC, RT and BM core) * AHBSTAT (AHB error status core) * GRADCDAC (Core interfacing to ADC/DAC hardware) * GRGPIO (GPIO port accessed from GPIO Library) * MCTRL (Memory controller settings configuration) * GRETH (10/100/1000 Ethernet driver using Driver manager) * GRPWM (Pulse Width Modulation core) * SPICTRL (SPI master interface) * GRSPW_ROUTER (SpaceWire Router AMBA configuration interface) * GRCTM (SpaceCraft on-board Time Management core) * SPWCUC (Time distribution over SpaceWire) * GRTC (SpaceCraft up-link Tele core) * GRTM (SpaceCraft down-link Tele Metry core) GR712RC ASIC specific interfaces: * GRASCS * CANMUX (select between OCCAN and SATCAN) * SATCAN * SLINK
Diffstat (limited to 'c/src/lib/libbsp/sparc/shared/time')
-rw-r--r--c/src/lib/libbsp/sparc/shared/time/grctm.c409
-rw-r--r--c/src/lib/libbsp/sparc/shared/time/spwcuc.c369
2 files changed, 778 insertions, 0 deletions
diff --git a/c/src/lib/libbsp/sparc/shared/time/grctm.c b/c/src/lib/libbsp/sparc/shared/time/grctm.c
new file mode 100644
index 0000000000..3185e13264
--- /dev/null
+++ b/c/src/lib/libbsp/sparc/shared/time/grctm.c
@@ -0,0 +1,409 @@
+/* GRCTM - CCSDS Time Manager - register driver interface.
+ *
+ * COPYRIGHT (c) 2009.
+ * Cobham 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 <grctm.h>
+
+/* Private structure of GRCTM driver */
+struct grctm_priv {
+ struct drvmgr_dev *dev;
+ struct grctm_regs *regs;
+ int open;
+
+ grctm_isr_t user_isr;
+ void *user_isr_arg;
+
+ struct grctm_stats stats;
+};
+
+void grctm_isr(void *data);
+
+struct amba_drv_info grctm_drv_info;
+
+void *grctm_open(int minor)
+{
+ struct grctm_priv *priv;
+ struct drvmgr_dev *dev;
+
+ /* Get Device from Minor */
+ if ( drvmgr_get_dev(&grctm_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 */
+ grctm_clr_stats(priv);
+ priv->user_isr = NULL;
+ priv->user_isr_arg = NULL;
+
+ return priv;
+}
+
+void grctm_close(void *grctm)
+{
+ struct grctm_priv *priv = (struct grctm_priv *)grctm;
+
+ if ( priv->open == 0 )
+ return;
+
+ /* Reset Hardware */
+ grctm_reset(priv);
+
+ priv->open = 0;
+}
+
+/* Hardware Reset of GRCTM */
+int grctm_reset(void *grctm)
+{
+ struct grctm_priv *priv = grctm;
+ struct grctm_regs *r = priv->regs;
+
+ r->grr = 0x55000001;
+
+ int i = 1000;
+ while ((r->grr & 1) && i > 0) {
+ i--;
+ }
+
+ return i ? 0 : -1;
+}
+
+void grctm_int_enable(void *grctm)
+{
+ struct grctm_priv *priv = (struct grctm_priv *)grctm;
+
+ /* Register and Enable Interrupt at Interrupt controller */
+ drvmgr_interrupt_register(priv->dev, 0, "grctm", grctm_isr, priv);
+}
+
+void grctm_int_disable(void *grctm)
+{
+ struct grctm_priv *priv = (struct grctm_priv *)grctm;
+
+ /* Enable Interrupt at Interrupt controller */
+ drvmgr_interrupt_unregister(priv->dev, 0, grctm_isr, priv);
+}
+
+void grctm_clr_stats(void *grctm)
+{
+ struct grctm_priv *priv = (struct grctm_priv *)grctm;
+
+ memset(&priv->stats, 0, sizeof(priv->stats));
+}
+
+void grctm_get_stats(void *grctm, struct grctm_stats *stats)
+{
+ struct grctm_priv *priv = (struct grctm_priv *)grctm;
+
+ memcpy(stats, &priv->stats, sizeof(priv->stats));
+}
+
+/* Enable external synchronisation (from grctm) */
+void grctm_enable_ext_sync(void *grctm)
+{
+ struct grctm_priv *priv = grctm;
+
+ priv->regs->gcr |= 0x55<<24 | 1<<9;
+}
+
+/* Disable external synchronisation (from grctm) */
+void grctm_disable_ext_sync(void *grctm)
+{
+ struct grctm_priv *priv = grctm;
+
+ priv->regs->gcr &= ~((0xAA<<24) | 1<<9);
+}
+
+/* Enable TimeWire synchronisation */
+void grctm_enable_tw_sync(void *grctm)
+{
+ struct grctm_priv *priv = grctm;
+
+ priv->regs->gcr |= 0x55<<24 | 1<<8;
+}
+
+/* Disable TimeWire synchronisation */
+void grctm_disable_tw_sync(void *grctm)
+{
+ struct grctm_priv *priv = grctm;
+
+ priv->regs->gcr &= ~((0xAA<<24) | 1<<8);
+}
+
+/* Disable frequency synthesizer from driving ET */
+void grctm_disable_fs(void *grctm)
+{
+ struct grctm_priv *priv = grctm;
+
+ priv->regs->gcr |= 0x55<<24 | 1<<7;
+}
+
+/* Enable frequency synthesizer to drive ET */
+void grctm_enable_fs(void *grctm)
+{
+ struct grctm_priv *priv = grctm;
+
+ priv->regs->gcr &= ~((0xAA<<24) | 1<<7);
+}
+
+/* Return elapsed coarse time */
+unsigned int grctm_get_et_coarse(void *grctm)
+{
+ struct grctm_priv *priv = grctm;
+
+ return priv->regs->etcr;
+}
+
+/* Return elapsed fine time */
+unsigned int grctm_get_et_fine(void *grctm)
+{
+ struct grctm_priv *priv = grctm;
+
+ return (priv->regs->etfr & 0xffffff00) >> 8;
+}
+
+/* Return elapsed time (coarse and fine) */
+unsigned long long grctm_get_et(void *grctm)
+{
+ return (((unsigned long)grctm_get_et_coarse(grctm)) << 24) | grctm_get_et_fine(grctm);
+}
+
+
+/* Return 1 if specified datation has been latched */
+int grctm_is_dat_latched(void *grctm, int dat)
+{
+ struct grctm_priv *priv = grctm;
+
+ return (priv->regs->gsr >> dat) & 1;
+}
+
+/* Set triggering edge of datation input */
+void grctm_set_dat_edge(void *grctm, int dat, int edge)
+{
+ struct grctm_priv *priv = grctm;
+
+ priv->regs->gcr &= ~((0xAA<<24) | 1 << (10+dat));
+ priv->regs->gcr |= 0x55<<24 | (edge&1) << (10+dat);
+}
+
+/* Return latched datation coarse time */
+unsigned int grctm_get_dat_coarse(void *grctm, int dat)
+{
+ struct grctm_priv *priv = grctm;
+
+ switch (dat) {
+ case 0 : return priv->regs->dcr0;
+ case 1 : return priv->regs->dcr1;
+ case 2 : return priv->regs->dcr2;
+ default: return -1;
+ }
+}
+
+/* Return latched datation fine time */
+unsigned int grctm_get_dat_fine(void *grctm, int dat)
+{
+ struct grctm_priv *priv = grctm;
+
+ switch (dat) {
+ case 0 : return (priv->regs->dfr0 & 0xffffff00) >> 8;
+ case 1 : return (priv->regs->dfr1 & 0xffffff00) >> 8;
+ case 2 : return (priv->regs->dfr2 & 0xffffff00) >> 8;
+ default: return -1;
+ }
+}
+
+
+/* Return latched datation ET */
+unsigned long long grctm_get_dat_et(void *grctm, int dat)
+{
+ return (((unsigned long)grctm_get_dat_coarse(grctm, dat)) << 24) |
+ grctm_get_dat_fine(grctm, dat);
+}
+
+
+/* Return current pulse configuration */
+unsigned int grctm_get_pulse_reg(void *grctm, int pulse)
+{
+ struct grctm_priv *priv = grctm;
+
+ return priv->regs->pdr[pulse];
+}
+
+/* Set pulse register */
+void grctm_set_pulse_reg(void *grctm, int pulse, unsigned int val)
+{
+ struct grctm_priv *priv = grctm;
+
+ priv->regs->pdr[pulse] = val;
+}
+
+/* Configure pulse: pp = period, pw = width, pl = level, en = enable */
+void grctm_cfg_pulse(void *grctm, int pulse, int pp, int pw, int pl, int en)
+{
+ grctm_set_pulse_reg(grctm, pulse, (pp&0xf)<<20 | (pw&0xf)<<16 | (pl&1)<<10 | (en&1)<<1);
+}
+
+/* Enable pulse output */
+void grctm_enable_pulse(void *grctm, int pulse)
+{
+ struct grctm_priv *priv = grctm;
+
+ priv->regs->pdr[pulse] |= 0x2;
+}
+
+/* Disable pulse output */
+void grctm_disable_pulse(void *grctm, int pulse)
+{
+ struct grctm_priv *priv = grctm;
+
+ priv->regs->pdr[pulse] &= ~0x2;
+}
+
+/* Clear interrupts */
+void grctm_clear_irqs(void *grctm, int irqs)
+{
+ struct grctm_priv *priv = grctm;
+
+ priv->regs->picr = irqs;
+}
+
+/* Enable interrupts */
+void grctm_enable_irqs(void *grctm, int irqs)
+{
+ struct grctm_priv *priv = grctm;
+
+ priv->regs->imr = irqs;
+}
+
+/* Set Frequency synthesizer increment */
+void grctm_set_fs_incr(void *grctm, int incr)
+{
+ struct grctm_priv *priv = grctm;
+
+ priv->regs->fsir = incr;
+}
+
+/* Set ET increment */
+void grctm_set_et_incr(void *grctm, int incr)
+{
+ struct grctm_priv *priv = grctm;
+
+ priv->regs->etir = incr;
+}
+
+
+void grctm_isr(void *data)
+{
+ struct grctm_priv *priv = data;
+ struct grctm_stats *stats = &priv->stats;
+ unsigned int pimr = priv->regs->pimr;
+
+ if ( pimr == 0 )
+ return;
+
+ stats->nirqs++;
+ if (pimr & PULSE0_IRQ )
+ stats->pulse++;
+
+ /* Let user Handle Interrupt */
+ if ( priv->user_isr )
+ priv->user_isr(pimr, priv->user_isr_arg);
+}
+
+struct grctm_regs *grctm_get_regs(void *grctm)
+{
+ struct grctm_priv *priv = (struct grctm_priv *)grctm;
+
+ return priv->regs;
+}
+
+void grctm_int_register(void *grctm, grctm_isr_t func, void *data)
+{
+ struct grctm_priv *priv = (struct grctm_priv *)grctm;
+
+ priv->user_isr = func;
+ priv->user_isr_arg = data;
+}
+
+/*** INTERFACE TO DRIVER MANAGER ***/
+
+int grctm_init2(struct drvmgr_dev *dev)
+{
+ struct amba_dev_info *ambadev;
+ struct ambapp_core *pnpinfo;
+ struct grctm_priv *priv;
+ struct grctm_regs *regs;
+
+ priv = (struct grctm_priv *)malloc(sizeof(*priv));
+ if ( priv == NULL )
+ return -1;
+ memset(priv, 0, sizeof(*priv));
+ priv->dev = dev;
+ dev->priv = priv;
+
+ /* Get device information from AMBA PnP information */
+ ambadev = (struct amba_dev_info *)dev->businfo;
+ if ( ambadev == NULL ) {
+ return -1;
+ }
+ pnpinfo = &ambadev->info;
+ regs = (struct grctm_regs *)pnpinfo->ahb_slv->start[0];
+
+ priv->regs = regs;
+
+ grctm_reset(priv);
+
+ return 0;
+}
+
+struct drvmgr_drv_ops grctm_ops =
+{
+ {NULL, grctm_init2, NULL, NULL},
+ NULL,
+ NULL
+};
+
+struct amba_dev_id grctm_ids[] =
+{
+ {VENDOR_GAISLER, GAISLER_GRCTM},
+ {0, 0} /* Mark end of table */
+};
+
+struct amba_drv_info grctm_drv_info =
+{
+ {
+ DRVMGR_OBJ_DRV, /* Driver */
+ NULL, /* Next driver */
+ NULL, /* Device list */
+ DRIVER_AMBAPP_GAISLER_GRCTM_ID, /* Driver ID */
+ "GRCTM_DRV", /* Driver Name */
+ DRVMGR_BUS_TYPE_AMBAPP, /* Bus Type */
+ &grctm_ops,
+ NULL, /* Funcs */
+ 0, /* No devices yet */
+ 0,
+ },
+ &grctm_ids[0]
+};
+
+/* Register the grctm Driver */
+void grctm_register(void)
+{
+ drvmgr_drv_register(&grctm_drv_info.general);
+}
diff --git a/c/src/lib/libbsp/sparc/shared/time/spwcuc.c b/c/src/lib/libbsp/sparc/shared/time/spwcuc.c
new file mode 100644
index 0000000000..738ec1a277
--- /dev/null
+++ b/c/src/lib/libbsp/sparc/shared/time/spwcuc.c
@@ -0,0 +1,369 @@
+/* SPWCUC - SpaceWire - CCSDS unsegmented Code Transfer Protocol GRLIB core
+ * register driver interface.
+ *
+ * COPYRIGHT (c) 2009.
+ * Cobham 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 <spwcuc.h>
+
+/* Private structure of SPWCUC driver. */
+struct spwcuc_priv {
+ struct drvmgr_dev *dev;
+ struct spwcuc_regs *regs;
+ int open;
+
+ spwcuc_isr_t user_isr;
+ void *user_isr_arg;
+
+ struct spwcuc_stats stats;
+};
+
+void spwcuc_isr(void *data);
+
+struct amba_drv_info spwcuc_drv_info;
+
+/* Hardware Reset of SPWCUC */
+int spwcuc_hw_reset(struct spwcuc_priv *priv)
+{
+ struct spwcuc_regs *r = priv->regs;
+ int i = 1000;
+
+ r->control = 1;
+
+ while ((r->control & 1) && i > 0) {
+ i--;
+ }
+
+ spwcuc_clear_irqs(priv, -1);
+
+ return i ? 0 : -1;
+}
+
+int spwcuc_reset(void *spwcuc)
+{
+ struct spwcuc_priv *priv = (struct spwcuc_priv *)spwcuc;
+
+ return spwcuc_hw_reset(priv);
+}
+
+void *spwcuc_open(int minor)
+{
+ struct spwcuc_priv *priv;
+ struct drvmgr_dev *dev;
+
+ /* Get Device from Minor */
+ if ( drvmgr_get_dev(&spwcuc_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 */
+ spwcuc_clr_stats(priv);
+ priv->user_isr = NULL;
+ priv->user_isr_arg = NULL;
+
+ return priv;
+}
+
+void spwcuc_close(void *spwcuc)
+{
+ struct spwcuc_priv *priv = (struct spwcuc_priv *)spwcuc;
+
+ if ( priv->open == 0 )
+ return;
+
+ /* Reset Hardware */
+ spwcuc_hw_reset(priv);
+
+ priv->open = 0;
+}
+
+void spwcuc_int_enable(void *spwcuc)
+{
+ struct spwcuc_priv *priv = (struct spwcuc_priv *)spwcuc;
+
+ /* Register and Enable Interrupt at Interrupt controller */
+ drvmgr_interrupt_register(priv->dev, 0, "spwcuc", spwcuc_isr, priv);
+}
+
+void spwcuc_int_disable(void *spwcuc)
+{
+ struct spwcuc_priv *priv = (struct spwcuc_priv *)spwcuc;
+
+ /* Enable Interrupt at Interrupt controller */
+ drvmgr_interrupt_unregister(priv->dev, 0, spwcuc_isr, priv);
+}
+
+void spwcuc_clr_stats(void *spwcuc)
+{
+ struct spwcuc_priv *priv = (struct spwcuc_priv *)spwcuc;
+
+ memset(&priv->stats, 0, sizeof(priv->stats));
+}
+
+void spwcuc_get_stats(void *spwcuc, struct spwcuc_stats *stats)
+{
+ struct spwcuc_priv *priv = (struct spwcuc_priv *)spwcuc;
+
+ memcpy(stats, &priv->stats, sizeof(priv->stats));
+}
+
+/* Configure the spwcuc core */
+void spwcuc_config(void *spwcuc, struct spwcuc_cfg *cfg)
+{
+ struct spwcuc_priv *priv = (struct spwcuc_priv *)spwcuc;
+ struct spwcuc_regs *r = priv->regs;
+
+ r->config = (cfg->sel_out & 0x1f) << 28 |
+ (cfg->sel_in & 0x1f) << 24 |
+ (cfg->mapping & 0x1f) << 16 |
+ (cfg->tolerance & 0x1f) << 8 |
+ (cfg->tid & 0x7) << 4 |
+ (cfg->ctf & 1) << 1 |
+ (cfg->cp & 1);
+
+ r->control = (cfg->txen & 1) << 1 |
+ (cfg->rxen & 1) << 2 |
+ (cfg->pktsyncen & 1) << 3 |
+ (cfg->pktiniten & 1) << 4 |
+ (cfg->pktrxen & 1) << 5;
+
+ r->dla = (cfg->dla_mask & 0xff)<<8 | (cfg->dla & 0xff);
+
+ r->pid = cfg->pid;
+
+ r->offset = cfg->offset;
+}
+
+/* Return elapsed coarse time */
+unsigned int spwcuc_get_et_coarse(void *spwcuc)
+{
+ struct spwcuc_priv *priv = (struct spwcuc_priv *)spwcuc;
+
+ return priv->regs->etct;
+}
+
+/* Return elapsed fine time */
+unsigned int spwcuc_get_et_fine(void *spwcuc)
+{
+ struct spwcuc_priv *priv = (struct spwcuc_priv *)spwcuc;
+
+ return (priv->regs->etft & 0xffffff) >> 8;
+}
+
+/* Return elapsed time (coarse and fine) */
+unsigned long long spwcuc_get_et(void *spwcuc)
+{
+ return (((unsigned long long)spwcuc_get_et_coarse(spwcuc)) << 24) | spwcuc_get_et_fine(spwcuc);
+}
+
+/* Return next elapsed coarse time (for use when sending SpW time packet) */
+unsigned int spwcuc_get_next_et_coarse(void *spwcuc)
+{
+ struct spwcuc_priv *priv = (struct spwcuc_priv *)spwcuc;
+
+ return priv->regs->etct_next;
+}
+
+/* Return next elapsed fine time (for use when sending SpW time packet) */
+unsigned int spwcuc_get_next_et_fine(void *spwcuc)
+{
+ struct spwcuc_priv *priv = (struct spwcuc_priv *)spwcuc;
+
+ return (priv->regs->etft_next & 0xffffff) >> 8;
+}
+
+/* Return next elapsed time (for use when sending SpW time packet) */
+unsigned long long spwcuc_get_next_et(void *spwcuc)
+{
+ return (((unsigned long long)spwcuc_get_next_et_coarse(spwcuc)) << 24) | spwcuc_get_next_et_fine(spwcuc);
+}
+
+/* Force/Set the elapsed time (coarse 32-bit and fine 24-bit) by writing the
+ * T-Field Time Packet Registers then the FORCE, NEW and INIT bits.
+ * The latter three are needed for the ET to be set with the new value.
+ */
+void spwcuc_force_et(void *spwcuc, unsigned long long time)
+{
+ struct spwcuc_priv *priv = (struct spwcuc_priv *)spwcuc;
+ struct spwcuc_regs *regs = priv->regs;
+
+ regs->etft_next = (time & 0xffffff) << 8;
+ regs->etct_next = (time >> 24) & 0xffffffff;
+ regs->pkt_pf_crc = (1 << 29) | (1 << 30) | (1 << 31);
+}
+
+/* Return received (from time packet) elapsed coarse time */
+unsigned int spwcuc_get_tp_et_coarse(void *spwcuc)
+{
+ struct spwcuc_priv *priv = (struct spwcuc_priv *)spwcuc;
+
+ return priv->regs->pkt_ct;
+}
+
+/* Return received (from time packet) elapsed fine time */
+unsigned int spwcuc_get_tp_et_fine(void *spwcuc)
+{
+ struct spwcuc_priv *priv = (struct spwcuc_priv *)spwcuc;
+
+ return (priv->regs->pkt_ft & 0xffffff) >> 8;
+}
+
+/* Return received (from time packet) elapsed time (coarse and fine) */
+unsigned long long spwcuc_get_tp_et(void *spwcuc)
+{
+ return (((unsigned long long)spwcuc_get_tp_et_coarse(spwcuc)) << 24) | spwcuc_get_tp_et_fine(spwcuc);
+}
+
+/* Clear interrupts */
+void spwcuc_clear_irqs(void *spwcuc, int irqs)
+{
+ struct spwcuc_priv *priv = (struct spwcuc_priv *)spwcuc;
+
+ priv->regs->picr = irqs;
+}
+
+/* Enable interrupts */
+void spwcuc_enable_irqs(void *spwcuc, int irqs)
+{
+ struct spwcuc_priv *priv = (struct spwcuc_priv *)spwcuc;
+
+ priv->regs->imr = irqs;
+}
+
+struct spwcuc_regs *spwcuc_get_regs(void *spwcuc)
+{
+ struct spwcuc_priv *priv = (struct spwcuc_priv *)spwcuc;
+
+ return priv->regs;
+}
+
+void spwcuc_int_register(void *spwcuc, spwcuc_isr_t func, void *data)
+{
+ struct spwcuc_priv *priv = (struct spwcuc_priv *)spwcuc;
+
+ priv->user_isr = func;
+ priv->user_isr_arg = data;
+}
+
+void spwcuc_isr(void *data)
+{
+ struct spwcuc_priv *priv = data;
+ struct spwcuc_stats *stats = &priv->stats;
+ unsigned int pimr = priv->regs->pimr;
+
+ stats->nirqs++;
+
+ if (pimr & PKT_INIT_IRQ)
+ stats->pkt_init++;
+ if (pimr & PKT_ERR_IRQ)
+ stats->pkt_err++;
+ if (pimr & PKT_RX_IRQ)
+ stats->pkt_rx++;
+ if (pimr & WRAP_ERR_IRQ)
+ stats->wraperr++;
+ if (pimr & WRAP_IRQ)
+ stats->wrap++;
+ if (pimr & SYNC_ERR_IRQ)
+ stats->syncerr++;
+ if (pimr & SYNC_IRQ)
+ stats->sync++;
+ if (pimr & TOL_ERR_IRQ)
+ stats->tolerr++;
+ if (pimr & TICK_RX_ERR_IRQ)
+ stats->tick_rx_error++;
+ if (pimr & TICK_RX_WRAP_IRQ)
+ stats->tick_rx_wrap++;
+ if (pimr & TICK_RX_IRQ)
+ stats->tick_rx++;
+ if (pimr & TICK_TX_WRAP_IRQ)
+ stats->tick_tx_wrap++;
+ if (pimr & TICK_TX_IRQ)
+ stats->tick_tx++;
+
+ /* Let user Handle Interrupt */
+ if ( priv->user_isr )
+ priv->user_isr(pimr, priv->user_isr_arg);
+}
+
+/*** INTERFACE TO DRIVER MANAGER ***/
+
+int spwcuc_init2(struct drvmgr_dev *dev)
+{
+ struct amba_dev_info *ambadev;
+ struct ambapp_core *pnpinfo;
+ struct spwcuc_priv *priv;
+ struct spwcuc_regs *regs;
+
+ priv = (struct spwcuc_priv *)malloc(sizeof(*priv));
+ if ( priv == NULL )
+ return -1;
+ memset(priv, 0, sizeof(*priv));
+ priv->dev = dev;
+ dev->priv = priv;
+
+ /* Get device information from AMBA PnP information */
+ ambadev = (struct amba_dev_info *)dev->businfo;
+ if ( ambadev == NULL ) {
+ return -1;
+ }
+ pnpinfo = &ambadev->info;
+ regs = (struct spwcuc_regs *)pnpinfo->apb_slv->start;
+
+ priv->regs = regs;
+
+ spwcuc_hw_reset(priv);
+
+ return 0;
+}
+
+struct drvmgr_drv_ops spwcuc_ops =
+{
+ {NULL, spwcuc_init2, NULL, NULL},
+ NULL,
+ NULL
+};
+
+struct amba_dev_id spwcuc_ids[] =
+{
+ {VENDOR_GAISLER, GAISLER_SPWCUC},
+ {0, 0} /* Mark end of table */
+};
+
+struct amba_drv_info spwcuc_drv_info =
+{
+ {
+ DRVMGR_OBJ_DRV, /* Driver */
+ NULL, /* Next driver */
+ NULL, /* Device list */
+ DRIVER_AMBAPP_GAISLER_SPWCUC_ID,/* Driver ID */
+ "SPWCUC_DRV", /* Driver Name */
+ DRVMGR_BUS_TYPE_AMBAPP, /* Bus Type */
+ &spwcuc_ops,
+ NULL, /* Funcs */
+ 0, /* No devices yet */
+ 0,
+ },
+ &spwcuc_ids[0]
+};
+
+/* Register the SPWCUC Driver */
+void spwcuc_register(void)
+{
+ drvmgr_drv_register(&spwcuc_drv_info.general);
+}