Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:24:07

0001 /* SPDX-License-Identifier: BSD-2-Clause */
0002 
0003 /*  GRCTM - CCSDS Time Manager - register driver interface.
0004  *
0005  *  COPYRIGHT (c) 2009.
0006  *  Cobham Gaisler AB.
0007  *
0008  * Redistribution and use in source and binary forms, with or without
0009  * modification, are permitted provided that the following conditions
0010  * are met:
0011  * 1. Redistributions of source code must retain the above copyright
0012  *    notice, this list of conditions and the following disclaimer.
0013  * 2. Redistributions in binary form must reproduce the above copyright
0014  *    notice, this list of conditions and the following disclaimer in the
0015  *    documentation and/or other materials provided with the distribution.
0016  *
0017  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
0018  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
0019  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
0020  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
0021  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
0022  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
0023  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
0024  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
0025  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
0026  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
0027  * POSSIBILITY OF SUCH DAMAGE.
0028  */
0029 
0030 #include <drvmgr/drvmgr.h>
0031 #include <grlib/ambapp_bus.h>
0032 #include <stdlib.h>
0033 #include <string.h>
0034 
0035 #include <grlib/grctm.h>
0036 
0037 #include <grlib/grlib_impl.h>
0038 
0039 /* Private structure of GRCTM driver */
0040 struct grctm_priv {
0041     struct drvmgr_dev *dev;
0042     struct grctm_regs *regs;
0043     int open;
0044 
0045     grctm_isr_t user_isr;
0046     void *user_isr_arg;
0047 
0048     struct grctm_stats stats;
0049 };
0050 
0051 void grctm_isr(void *data);
0052 
0053 struct amba_drv_info grctm_drv_info;
0054 
0055 void *grctm_open(int minor)
0056 {
0057     struct grctm_priv *priv;
0058     struct drvmgr_dev *dev;
0059 
0060     /* Get Device from Minor */
0061     if ( drvmgr_get_dev(&grctm_drv_info.general, minor, &dev) ) {
0062         return NULL;
0063     }
0064 
0065     priv = dev->priv;
0066     if ( (priv == NULL) || priv->open )
0067         return NULL;
0068 
0069     /* Set initial state of software */
0070     priv->open = 1;
0071 
0072     /* Clear Statistics */
0073     grctm_clr_stats(priv);
0074     priv->user_isr = NULL;
0075     priv->user_isr_arg = NULL;
0076 
0077     return priv;
0078 }
0079 
0080 void grctm_close(void *grctm)
0081 {
0082     struct grctm_priv *priv = (struct grctm_priv *)grctm;
0083 
0084     if ( priv->open == 0 )
0085         return;
0086 
0087     /* Reset Hardware */
0088     grctm_reset(priv);
0089 
0090     priv->open = 0;
0091 }
0092 
0093 /* Hardware Reset of GRCTM */
0094 int grctm_reset(void *grctm)
0095 {
0096     struct grctm_priv *priv = grctm;
0097     struct grctm_regs *r = priv->regs;
0098 
0099     r->grr = 0x55000001;
0100 
0101     int i = 1000;
0102     while ((r->grr & 1) && i > 0) {
0103         i--;
0104     }
0105 
0106     return i ? 0 : -1;
0107 }
0108 
0109 void grctm_int_enable(void *grctm)
0110 {
0111     struct grctm_priv *priv = (struct grctm_priv *)grctm;
0112 
0113     /* Register and Enable Interrupt at Interrupt controller */
0114     drvmgr_interrupt_register(priv->dev, 0, "grctm", grctm_isr, priv);
0115 }
0116 
0117 void grctm_int_disable(void *grctm)
0118 {
0119     struct grctm_priv *priv = (struct grctm_priv *)grctm;
0120 
0121     /* Enable Interrupt at Interrupt controller */
0122     drvmgr_interrupt_unregister(priv->dev, 0, grctm_isr, priv);
0123 }
0124 
0125 void grctm_clr_stats(void *grctm)
0126 {
0127     struct grctm_priv *priv = (struct grctm_priv *)grctm;
0128 
0129     memset(&priv->stats, 0, sizeof(priv->stats));
0130 }
0131 
0132 void grctm_get_stats(void *grctm, struct grctm_stats *stats)
0133 {
0134     struct grctm_priv *priv = (struct grctm_priv *)grctm;
0135 
0136     memcpy(stats, &priv->stats, sizeof(priv->stats));
0137 }
0138 
0139 /* Enable external synchronisation (from grctm) */
0140 void grctm_enable_ext_sync(void *grctm)
0141 {
0142     struct grctm_priv *priv = grctm;
0143 
0144     priv->regs->gcr |= 0x55<<24 | 1<<9;
0145 }
0146 
0147 /* Disable external synchronisation (from grctm) */
0148 void grctm_disable_ext_sync(void *grctm)
0149 {
0150     struct grctm_priv *priv = grctm;
0151 
0152     priv->regs->gcr &= ~((0xAA<<24) | 1<<9);
0153 }
0154 
0155 /* Enable TimeWire synchronisation */
0156 void grctm_enable_tw_sync(void *grctm)
0157 {
0158     struct grctm_priv *priv = grctm;
0159 
0160     priv->regs->gcr |= 0x55<<24 | 1<<8;
0161 }
0162 
0163 /* Disable TimeWire synchronisation */
0164 void grctm_disable_tw_sync(void *grctm)
0165 {
0166     struct grctm_priv *priv = grctm;
0167 
0168     priv->regs->gcr &= ~((0xAA<<24) | 1<<8);
0169 }
0170 
0171 /* Disable frequency synthesizer from driving ET */
0172 void grctm_disable_fs(void *grctm)
0173 {
0174     struct grctm_priv *priv = grctm;
0175 
0176     priv->regs->gcr |= 0x55<<24 | 1<<7;
0177 }
0178 
0179 /* Enable frequency synthesizer to drive ET */
0180 void grctm_enable_fs(void *grctm)
0181 {
0182     struct grctm_priv *priv = grctm;
0183 
0184     priv->regs->gcr &= ~((0xAA<<24) | 1<<7);
0185 }
0186 
0187 /* Return elapsed coarse time */
0188 unsigned int grctm_get_et_coarse(void *grctm)
0189 {
0190     struct grctm_priv *priv = grctm;
0191 
0192     return priv->regs->etcr;
0193 }
0194 
0195 /* Return elapsed fine time */
0196 unsigned int grctm_get_et_fine(void *grctm)
0197 {
0198     struct grctm_priv *priv = grctm;
0199 
0200     return (priv->regs->etfr & 0xffffff00) >> 8;
0201 }
0202 
0203 /* Return elapsed time (coarse and fine) */
0204 unsigned long long grctm_get_et(void *grctm)
0205 {
0206     return (((unsigned long)grctm_get_et_coarse(grctm)) << 24) | grctm_get_et_fine(grctm);
0207 }
0208 
0209 
0210 /* Return 1 if specified datation has been latched */
0211 int grctm_is_dat_latched(void *grctm, int dat)
0212 {
0213     struct grctm_priv *priv = grctm;
0214 
0215     return (priv->regs->gsr >> dat) & 1;
0216 }
0217 
0218 /* Set triggering edge of datation input */
0219 void grctm_set_dat_edge(void *grctm, int dat, int edge)
0220 {
0221     struct grctm_priv *priv = grctm;
0222 
0223     priv->regs->gcr &= ~((0xAA<<24) | 1 << (10+dat));
0224     priv->regs->gcr |= 0x55<<24 | (edge&1) << (10+dat);
0225 }
0226 
0227 /* Return latched datation coarse time */
0228 unsigned int grctm_get_dat_coarse(void *grctm, int dat)
0229 {
0230     struct grctm_priv *priv = grctm;
0231 
0232     switch (dat) {
0233     case 0 : return priv->regs->dcr0; 
0234     case 1 : return priv->regs->dcr1;
0235     case 2 : return priv->regs->dcr2;
0236     default: return -1;
0237     }
0238 }
0239 
0240 /* Return latched datation fine time */
0241 unsigned int grctm_get_dat_fine(void *grctm, int dat)
0242 {
0243     struct grctm_priv *priv = grctm;
0244 
0245     switch (dat) {
0246     case 0 : return (priv->regs->dfr0 & 0xffffff00) >> 8; 
0247     case 1 : return (priv->regs->dfr1 & 0xffffff00) >> 8;
0248     case 2 : return (priv->regs->dfr2 & 0xffffff00) >> 8;
0249     default: return -1;
0250     }
0251 }
0252 
0253 
0254 /* Return latched datation ET */
0255 unsigned long long grctm_get_dat_et(void *grctm, int dat)
0256 {
0257     return (((unsigned long)grctm_get_dat_coarse(grctm, dat)) << 24) | 
0258         grctm_get_dat_fine(grctm, dat);
0259 }
0260 
0261 
0262 /* Return current pulse configuration */
0263 unsigned int grctm_get_pulse_reg(void *grctm, int pulse)
0264 {
0265     struct grctm_priv *priv = grctm;
0266 
0267     return priv->regs->pdr[pulse];
0268 }
0269 
0270 /* Set pulse register */
0271 void grctm_set_pulse_reg(void *grctm, int pulse, unsigned int val)
0272 {
0273     struct grctm_priv *priv = grctm;
0274 
0275     priv->regs->pdr[pulse] = val;
0276 }
0277 
0278 /* Configure pulse: pp = period, pw = width, pl = level, en = enable */
0279 void grctm_cfg_pulse(void *grctm, int pulse, int pp, int pw, int pl, int en)
0280 {
0281     grctm_set_pulse_reg(grctm, pulse, (pp&0xf)<<20 | (pw&0xf)<<16 | (pl&1)<<10 | (en&1)<<1);
0282 }
0283 
0284 /* Enable pulse output */
0285 void grctm_enable_pulse(void *grctm, int pulse)
0286 {
0287     struct grctm_priv *priv = grctm;
0288 
0289     priv->regs->pdr[pulse] |= 0x2;
0290 }
0291 
0292 /* Disable pulse output */
0293 void grctm_disable_pulse(void *grctm, int pulse)
0294 {
0295     struct grctm_priv *priv = grctm;
0296 
0297     priv->regs->pdr[pulse] &= ~0x2;
0298 }
0299 
0300 /* Clear interrupts */
0301 void grctm_clear_irqs(void *grctm, int irqs)
0302 {
0303     struct grctm_priv *priv = grctm;
0304 
0305     priv->regs->picr = irqs;
0306 }
0307 
0308 /* Enable interrupts */
0309 void grctm_enable_irqs(void *grctm, int irqs)
0310 {
0311     struct grctm_priv *priv = grctm;
0312 
0313     priv->regs->imr  = irqs;
0314 }
0315 
0316 /* Set Frequency synthesizer increment */
0317 void grctm_set_fs_incr(void *grctm, int incr)
0318 {
0319     struct grctm_priv *priv = grctm;
0320 
0321     priv->regs->fsir  = incr;
0322 }
0323 
0324 /* Set ET increment */
0325 void grctm_set_et_incr(void *grctm, int incr)
0326 {
0327     struct grctm_priv *priv = grctm;
0328 
0329     priv->regs->etir  = incr;
0330 }
0331 
0332 
0333 void grctm_isr(void *data)
0334 {
0335     struct grctm_priv *priv = data;
0336     struct grctm_stats *stats = &priv->stats;
0337     unsigned int pimr = priv->regs->pimr;
0338 
0339     if ( pimr == 0 )
0340         return;
0341 
0342     stats->nirqs++;
0343     if (pimr & PULSE0_IRQ )
0344         stats->pulse++;
0345 
0346     /* Let user Handle Interrupt */
0347     if ( priv->user_isr )
0348         priv->user_isr(pimr, priv->user_isr_arg);
0349 }
0350 
0351 struct grctm_regs *grctm_get_regs(void *grctm)
0352 {
0353     struct grctm_priv *priv = (struct grctm_priv *)grctm;
0354 
0355     return priv->regs;
0356 }
0357 
0358 void grctm_int_register(void *grctm, grctm_isr_t func, void *data)
0359 {
0360     struct grctm_priv *priv = (struct grctm_priv *)grctm;
0361 
0362     priv->user_isr = func;
0363     priv->user_isr_arg = data;
0364 }
0365 
0366 /*** INTERFACE TO DRIVER MANAGER ***/
0367 
0368 static int grctm_init2(struct drvmgr_dev *dev)
0369 {
0370     struct amba_dev_info *ambadev;
0371     struct ambapp_core *pnpinfo;
0372     struct grctm_priv *priv;
0373     struct grctm_regs *regs;
0374 
0375     priv = grlib_calloc(1, sizeof(*priv));
0376     if ( priv == NULL )
0377         return -1;
0378     priv->dev = dev;
0379     dev->priv = priv;
0380 
0381     /* Get device information from AMBA PnP information */
0382     ambadev = (struct amba_dev_info *)dev->businfo;
0383     if ( ambadev == NULL ) {
0384         return -1;
0385     }
0386     pnpinfo = &ambadev->info;
0387     regs = (struct grctm_regs *)pnpinfo->ahb_slv->start[0];
0388 
0389     priv->regs = regs;
0390 
0391     grctm_reset(priv);
0392 
0393     return 0;
0394 }
0395 
0396 struct drvmgr_drv_ops grctm_ops =
0397 {
0398     {NULL, grctm_init2, NULL, NULL},
0399     NULL,
0400     NULL
0401 };
0402 
0403 struct amba_dev_id grctm_ids[] =
0404 {
0405     {VENDOR_GAISLER, GAISLER_GRCTM},
0406     {0, 0}  /* Mark end of table */
0407 };
0408 
0409 struct amba_drv_info grctm_drv_info =
0410 {
0411     {
0412         DRVMGR_OBJ_DRV,         /* Driver */
0413         NULL,               /* Next driver */
0414         NULL,               /* Device list */
0415         DRIVER_AMBAPP_GAISLER_GRCTM_ID, /* Driver ID */
0416         "GRCTM_DRV",            /* Driver Name */
0417         DRVMGR_BUS_TYPE_AMBAPP,     /* Bus Type */
0418         &grctm_ops,
0419         NULL,               /* Funcs */
0420         0,              /* No devices yet */
0421         0,
0422     },
0423     &grctm_ids[0]
0424 };
0425 
0426 /* Register the grctm Driver */
0427 void grctm_register(void)
0428 {
0429     drvmgr_drv_register(&grctm_drv_info.general);
0430 }