Back to home page

LXR

 
 

    


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

0001 /* SPDX-License-Identifier: BSD-2-Clause */
0002 
0003 /*  This file contains the driver for the GRLIB GPTIMER timers port. The driver
0004  *  is implemented by using the tlib.c simple timer layer and the Driver
0005  *  Manager.
0006  *
0007  *  The Driver can be configured using driver resources:
0008  *
0009  *  - timerStart  Timer Index if first Timer, this parameters is typically used
0010  *                in AMP systems for resource allocation. The Timers before
0011  *                timerStart will not be accessed.
0012  *  - timerCnt    Number of timers that the driver will use, this parameters is
0013  *                typically used in AMP systems for resource allocation between
0014  *                OS instances.
0015  *  - prescaler   Base prescaler, normally set by bootloader but can be
0016  *                overridden. The default scaler reload value set by bootloader
0017  *                is so that Timers operate in 1MHz. Setting the prescaler to a
0018  *                lower value increase the accuracy of the timers but shortens
0019  *                the time until underflow happens.
0020  *  - clockTimer  Used to select a particular timer to be the system clock
0021  *                timer. This is useful when multiple GPTIMERs cores are
0022  *                available, or in AMP systems. By default the TLIB selects the
0023  *                first timer registered as system clock timer.
0024  *
0025  *  The BSP define APBUART_INFO_AVAIL in order to add the info routine
0026  *  used for debugging.
0027  *
0028  *  COPYRIGHT (c) 2010.
0029  *  Cobham Gaisler AB.
0030  *
0031  * Redistribution and use in source and binary forms, with or without
0032  * modification, are permitted provided that the following conditions
0033  * are met:
0034  * 1. Redistributions of source code must retain the above copyright
0035  *    notice, this list of conditions and the following disclaimer.
0036  * 2. Redistributions in binary form must reproduce the above copyright
0037  *    notice, this list of conditions and the following disclaimer in the
0038  *    documentation and/or other materials provided with the distribution.
0039  *
0040  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
0041  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
0042  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
0043  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
0044  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
0045  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
0046  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
0047  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
0048  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
0049  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
0050  * POSSIBILITY OF SUCH DAMAGE.
0051  */
0052 
0053 #include <drvmgr/drvmgr.h>
0054 #include <grlib/ambapp_bus.h>
0055 #include <grlib/gptimer.h>
0056 #include <grlib/gptimer-regs.h>
0057 #include <grlib/io.h>
0058 #include <grlib/tlib.h>
0059 
0060 #if defined(LEON3)
0061 #include <bsp/leon3.h>
0062 #endif
0063 
0064 #ifdef GPTIMER_INFO_AVAIL
0065 #include <stdio.h>
0066 #endif
0067 
0068 #ifdef RTEMS_SMP
0069 #include <rtems/score/processormask.h>
0070 #include <rtems/score/smpimpl.h>
0071 #endif
0072 
0073 #include <grlib/grlib_impl.h>
0074 
0075 #define DBG(x...)
0076 
0077 /* GPTIMER timer private */
0078 struct gptimer_timer_priv {
0079     struct tlib_dev tdev;   /* Must be first in struct */
0080     gptimer_timer *tregs;
0081     char index; /* Timer Index in this driver */
0082     char tindex; /* Timer Index In Hardware */
0083     uint32_t irq_ack_mask;
0084 };
0085 
0086 /* GPTIMER Core private */
0087 struct gptimer_priv {
0088     struct drvmgr_dev *dev;
0089     gptimer *regs;
0090     unsigned int base_clk;
0091     unsigned int base_freq;
0092     unsigned int widthmask;
0093     char separate_interrupt;
0094     char isr_installed;
0095 
0096     /* Structure per Timer unit, the core supports up to 8 timers */
0097     int timer_cnt;
0098     struct gptimer_timer_priv timers[0];
0099 };
0100 
0101 void gptimer_isr(void *data);
0102 
0103 #if 0
0104 void gptimer_tlib_irq_register(struct tlib_drv *tdrv, tlib_isr_t func, void *data)
0105 {
0106     struct gptimer_priv *priv = (struct gptimer_priv *)tdrv;
0107 
0108     if ( SHARED ...)
0109     
0110     
0111     drvmgr_interrupt_register();
0112 }
0113 #endif
0114 
0115 /******************* Driver manager interface ***********************/
0116 
0117 /* Driver prototypes */
0118 static struct tlib_drv gptimer_tlib_drv;
0119 int gptimer_device_init(struct gptimer_priv *priv);
0120 
0121 int gptimer_init1(struct drvmgr_dev *dev);
0122 #ifdef GPTIMER_INFO_AVAIL
0123 static int gptimer_info(
0124     struct drvmgr_dev *dev,
0125     void (*print_line)(void *p, char *str),
0126     void *p, int, char *argv[]);
0127 #define GTIMER_INFO_FUNC gptimer_info
0128 #else
0129 #define GTIMER_INFO_FUNC NULL
0130 #endif
0131 
0132 struct drvmgr_drv_ops gptimer_ops =
0133 {
0134     .init = {gptimer_init1, NULL, NULL, NULL},
0135     .remove = NULL,
0136     .info = GTIMER_INFO_FUNC,
0137 };
0138 
0139 struct amba_dev_id gptimer_ids[] =
0140 {
0141     {VENDOR_GAISLER, GAISLER_GPTIMER},
0142     {VENDOR_GAISLER, GAISLER_GRTIMER},
0143     {0, 0}      /* Mark end of table */
0144 };
0145 
0146 struct amba_drv_info gptimer_drv_info =
0147 {
0148     {
0149         DRVMGR_OBJ_DRV,         /* Driver */
0150         NULL,               /* Next driver */
0151         NULL,               /* Device list */
0152         DRIVER_AMBAPP_GAISLER_GPTIMER_ID,/* Driver ID */
0153         "GPTIMER_DRV",          /* Driver Name */
0154         DRVMGR_BUS_TYPE_AMBAPP,     /* Bus Type */
0155         &gptimer_ops,
0156         NULL,               /* Funcs */
0157         0,              /* No devices yet */
0158         0,
0159     },
0160     &gptimer_ids[0]
0161 };
0162 
0163 void gptimer_register_drv (void)
0164 {
0165     DBG("Registering GPTIMER driver\n");
0166     drvmgr_drv_register(&gptimer_drv_info.general);
0167 }
0168 
0169 int gptimer_init1(struct drvmgr_dev *dev)
0170 {
0171     struct gptimer_priv *priv;
0172     gptimer *regs;
0173     struct amba_dev_info *ambadev;
0174     struct ambapp_core *pnpinfo;
0175     int timer_hw_cnt, timer_cnt, timer_start;
0176     int i, size;
0177     struct gptimer_timer_priv *timer;
0178     union drvmgr_key_value *value;
0179     uint32_t irq_ack_mask;
0180 
0181     /* Get device information from AMBA PnP information */
0182     ambadev = (struct amba_dev_info *)dev->businfo;
0183     if ( ambadev == NULL ) {
0184         return -1;
0185     }
0186     pnpinfo = &ambadev->info;
0187     regs = (gptimer *)pnpinfo->apb_slv->start;
0188 
0189     DBG("GPTIMER[%d] on bus %s\n", dev->minor_drv, dev->parent->dev->name);
0190 
0191     /* Get number of Timers */
0192     timer_hw_cnt = GPTIMER_CONFIG_TIMERS_GET(grlib_load_32(&regs->config));
0193 
0194     /* Let user spelect a range of timers to be used. In AMP systems
0195      * it is sometimes neccessary to leave timers for other CPU instances.
0196      *
0197      * The default operation in AMP is to shared the timers within the
0198      * first GPTIMER core as below. This can of course be overrided by
0199      * driver resources.
0200      */
0201     timer_cnt = timer_hw_cnt;
0202     timer_start = 0;
0203 #if defined(RTEMS_MULTIPROCESSING) && defined(LEON3)
0204     if ((dev->minor_drv == 0) && drvmgr_on_rootbus(dev)) {
0205         timer_cnt = 1;
0206         timer_start = LEON3_Cpu_Index;
0207     }
0208 #endif
0209     value = drvmgr_dev_key_get(dev, "timerStart", DRVMGR_KT_INT);
0210     if ( value) {
0211         timer_start = value->i;
0212         timer_cnt = timer_hw_cnt - timer_start;
0213     }
0214     value = drvmgr_dev_key_get(dev, "timerCnt", DRVMGR_KT_INT);
0215     if ( value && (value->i < timer_cnt) ) {
0216         timer_cnt = value->i;
0217     }
0218 
0219     /* Allocate Common Timer Description, size depends on how many timers
0220      * are present.
0221      */
0222     size = sizeof(struct gptimer_priv) +
0223         timer_cnt*sizeof(struct gptimer_timer_priv);
0224     priv = dev->priv = grlib_calloc(1, size);
0225     if ( !priv )
0226         return DRVMGR_NOMEM;
0227     priv->dev = dev;
0228     priv->regs = regs;
0229 
0230     /* The Base Frequency of the GPTIMER core is the same as the
0231      * frequency of the AMBA bus it is situated on.
0232      */
0233     drvmgr_freq_get(dev, DEV_APB_SLV, &priv->base_clk);
0234 
0235     /* This core will may provide important Timer functionality
0236      * to other drivers and the RTEMS kernel, the Clock driver
0237      * may for example use this device. So the Timer driver must be
0238      * initialized in the first iiitialization stage.
0239      */
0240 
0241     /*** Initialize Hardware ***/
0242 
0243     /* If user request to set prescaler, we will do that. However, note
0244      * that doing so for the Root-Bus GPTIMER may affect the RTEMS Clock
0245      * so that Clock frequency is wrong.
0246      */
0247     value = drvmgr_dev_key_get(priv->dev, "prescaler", DRVMGR_KT_INT);
0248     if ( value )
0249         grlib_store_32(&regs->sreload, value->i);
0250 
0251     /* Get Frequency that the timers are operating in (after prescaler) */
0252     priv->base_freq = priv->base_clk / (grlib_load_32(&regs->sreload) + 1);
0253 
0254     /* Stop Timer and probe Pending bit. In newer hardware the
0255      * timer has pending bit is cleared by writing a one to it,
0256      * whereas older versions it is cleared with a zero.
0257      */
0258     grlib_store_32(&regs->timer[timer_start].tctrl, GPTIMER_TCTRL_IP);
0259     if ((grlib_load_32(&regs->timer[timer_start].tctrl) & GPTIMER_TCTRL_IP) != 0)
0260         irq_ack_mask = ~GPTIMER_TCTRL_IP;
0261     else
0262         irq_ack_mask = ~0U;
0263 
0264     /* Probe timer register width mask */
0265     grlib_store_32(&regs->timer[timer_start].tcntval, 0xffffffff);
0266     priv->widthmask = grlib_load_32(&regs->timer[timer_start].tcntval);
0267 
0268     priv->timer_cnt = timer_cnt;
0269     for (i=0; i<timer_cnt; i++) {
0270         timer = &priv->timers[i];
0271         timer->index = i;
0272         timer->tindex = i + timer_start;
0273         timer->tregs = &regs->timer[(int)timer->tindex];
0274         timer->tdev.drv = &gptimer_tlib_drv;
0275         timer->irq_ack_mask = irq_ack_mask;
0276 
0277         /* Register Timer at Timer Library */
0278         tlib_dev_reg(&timer->tdev);
0279     }
0280 
0281     /* Check Interrupt support implementation, two cases:
0282      *  A. All Timers share one IRQ
0283      *  B. Each Timer have an individual IRQ. The number is:
0284      *        BASE_IRQ + timer_index
0285      */
0286     priv->separate_interrupt = (grlib_load_32(&regs->config) & GPTIMER_CONFIG_SI) != 0;
0287 
0288     return DRVMGR_OK;
0289 }
0290 
0291 #ifdef GPTIMER_INFO_AVAIL
0292 static int gptimer_info(
0293     struct drvmgr_dev *dev,
0294     void (*print_line)(void *p, char *str),
0295     void *p, int argc, char *argv[])
0296 {
0297     struct gptimer_priv *priv = dev->priv;
0298     struct gptimer_timer_priv *timer;
0299     char buf[64];
0300     int i;
0301 
0302     if (priv == NULL || argc != 0)
0303         return -DRVMGR_EINVAL;
0304 
0305     sprintf(buf, "Timer Count: %d", priv->timer_cnt);
0306     print_line(p, buf);
0307     sprintf(buf, "REGS:        0x%08x", (unsigned int)priv->regs);
0308     print_line(p, buf);
0309     sprintf(buf, "BASE SCALER: %d", grlib_load_32(&priv->regs->sreload));
0310     print_line(p, buf);
0311     sprintf(buf, "BASE FREQ:   %dkHz", priv->base_freq / 1000);
0312     print_line(p, buf);
0313     sprintf(buf, "SeparateIRQ: %s", priv->separate_interrupt ? "YES":"NO");
0314     print_line(p, buf);
0315 
0316     for (i=0; i<priv->timer_cnt; i++) {
0317         timer = &priv->timers[i];
0318         sprintf(buf, " - TIMER HW Index %d -", timer->tindex);
0319         print_line(p, buf);
0320         sprintf(buf, " TLIB Index: %d", timer->index);
0321         print_line(p, buf);
0322         sprintf(buf, " RELOAD REG: %d", grlib_load_32(&timer->tregs->trldval));
0323         print_line(p, buf);
0324         sprintf(buf, " CTRL REG:   %d", grlib_load_32(&timer->tregs->tctrl));
0325         print_line(p, buf);
0326     }
0327 
0328     return DRVMGR_OK;
0329 }
0330 #endif
0331 
0332 static inline struct gptimer_priv *priv_from_timer(struct gptimer_timer_priv *t)
0333 {
0334     return (struct gptimer_priv *)
0335         ((unsigned int)t -
0336         sizeof(struct gptimer_priv) -
0337         t->index * sizeof(struct gptimer_timer_priv));
0338 }
0339 
0340 static int gptimer_tlib_int_pend(struct tlib_dev *hand, int ack)
0341 {
0342     struct gptimer_timer_priv *timer = (struct gptimer_timer_priv *)hand;
0343     uint32_t tctrl;
0344 
0345     tctrl = grlib_load_32(&timer->tregs->tctrl);
0346 
0347     if ((tctrl & (GPTIMER_TCTRL_IP | GPTIMER_TCTRL_IE)) ==
0348         (GPTIMER_TCTRL_IP | GPTIMER_TCTRL_IE)) {
0349         /* clear Pending IRQ ? */
0350         if (ack) {
0351             tctrl &= timer->irq_ack_mask;
0352             grlib_store_32(&timer->tregs->tctrl, tctrl);
0353         }
0354         return 1; /* timer generated IRQ */
0355     } else
0356         return 0; /* was not timer causing IRQ */
0357 }
0358 
0359 void gptimer_isr(void *data)
0360 {
0361     struct gptimer_priv *priv = data;
0362     int i;
0363 
0364     /* Check all timers for IRQ */
0365     for (i=0;i<priv->timer_cnt; i++) {
0366         if (gptimer_tlib_int_pend((void *)&priv->timers[i], 0)) {
0367             /* IRQ Was generated by Timer and Pending flag has *not*
0368              * yet been cleared, this is to allow ISR to look at
0369              * pending bit. Call ISR registered. Clear pending bit.
0370              */
0371             if (priv->timers[i].tdev.isr_func) {
0372                 priv->timers[i].tdev.isr_func(
0373                     priv->timers[i].tdev.isr_data);
0374             }
0375             gptimer_tlib_int_pend((void *)&priv->timers[i], 1);
0376         }
0377     }
0378 }
0379 
0380 static void gptimer_tlib_reset(struct tlib_dev *hand)
0381 {
0382     struct gptimer_timer_priv *timer = (struct gptimer_timer_priv *)hand;
0383     uint32_t tctrl;
0384 
0385     tctrl = grlib_load_32(&timer->tregs->tctrl);
0386     tctrl &= timer->irq_ack_mask;
0387     tctrl &= GPTIMER_TCTRL_IP;
0388     grlib_store_32(&timer->tregs->tctrl, tctrl);
0389     grlib_store_32(&timer->tregs->trldval, 0xffffffff);
0390     grlib_store_32(&timer->tregs->tctrl, GPTIMER_TCTRL_LD);
0391 }
0392 
0393 static void gptimer_tlib_get_freq(
0394     struct tlib_dev *hand,
0395     unsigned int *basefreq,
0396     unsigned int *tickrate)
0397 {
0398     struct gptimer_timer_priv *timer = (struct gptimer_timer_priv *)hand;
0399     struct gptimer_priv *priv = priv_from_timer(timer);
0400 
0401     /* Calculate base frequency from Timer Clock and Prescaler */
0402     if ( basefreq )
0403         *basefreq = priv->base_freq;
0404     if ( tickrate )
0405         *tickrate = grlib_load_32(&timer->tregs->trldval) + 1;
0406 }
0407 
0408 static int gptimer_tlib_set_freq(struct tlib_dev *hand, unsigned int tickrate)
0409 {
0410     struct gptimer_timer_priv *timer = (struct gptimer_timer_priv *)hand;
0411 
0412     grlib_store_32(&timer->tregs->trldval, tickrate - 1);
0413 
0414     /*Check that value was allowed (Timer may not be as wide as expected)*/
0415     if (grlib_load_32(&timer->tregs->trldval) != (tickrate - 1))
0416         return -1;
0417     else
0418         return 0;
0419 }
0420 
0421 static void gptimer_tlib_irq_reg(struct tlib_dev *hand, tlib_isr_t func, void *data, int flags)
0422 {
0423     struct gptimer_timer_priv *timer = (struct gptimer_timer_priv *)hand;
0424     struct gptimer_priv *priv = priv_from_timer(timer);
0425     uint32_t tctrl;
0426 
0427     if ( priv->separate_interrupt ) {
0428         drvmgr_interrupt_register(priv->dev, timer->tindex,
0429                         "gptimer", func, data);
0430     } else {
0431         if (priv->isr_installed == 0) {
0432             /* Shared IRQ handler */
0433             drvmgr_interrupt_register(
0434                 priv->dev,
0435                 0,
0436                 "gptimer_shared",
0437                 gptimer_isr,
0438                 priv);
0439         }
0440         priv->isr_installed++;
0441     }
0442 
0443 #if RTEMS_SMP
0444     if (flags & TLIB_FLAGS_BROADCAST) {
0445         int tindex = 0;
0446 
0447         if (priv->separate_interrupt) {
0448             /* Offset interrupt number with HW subtimer index */
0449             tindex = timer->tindex;
0450         }
0451         drvmgr_interrupt_set_affinity(priv->dev, tindex,
0452                           _SMP_Get_online_processors());
0453     }
0454 #endif
0455 
0456     tctrl = grlib_load_32(&timer->tregs->tctrl);
0457     tctrl |= GPTIMER_TCTRL_IE;
0458     grlib_store_32(&timer->tregs->tctrl, tctrl);
0459 }
0460 
0461 static void gptimer_tlib_irq_unreg(struct tlib_dev *hand, tlib_isr_t func, void *data)
0462 {
0463     struct gptimer_timer_priv *timer = (struct gptimer_timer_priv *)hand;
0464     struct gptimer_priv *priv = priv_from_timer(timer);
0465     uint32_t tctrl;
0466 
0467     /* Turn off IRQ at source, unregister IRQ handler */
0468     tctrl = grlib_load_32(&timer->tregs->tctrl);
0469     tctrl &= ~GPTIMER_TCTRL_IE;
0470     grlib_store_32(&timer->tregs->tctrl, tctrl);
0471 
0472     if ( priv->separate_interrupt ) {
0473         drvmgr_interrupt_unregister(priv->dev, timer->tindex,
0474                         func, data);
0475     } else {
0476         timer->tdev.isr_func = NULL;
0477         priv->isr_installed--;
0478         if (priv->isr_installed == 0) {
0479             drvmgr_interrupt_unregister(priv->dev, 0,
0480                             gptimer_isr, priv);
0481         }
0482     }
0483 }
0484 
0485 static void gptimer_tlib_start(struct tlib_dev *hand, int once)
0486 {
0487     struct gptimer_timer_priv *timer = (struct gptimer_timer_priv *)hand;
0488     uint32_t tctrl;
0489 
0490     /* Load the selected frequency before starting Frequency */
0491     tctrl = grlib_load_32(&timer->tregs->tctrl);
0492     tctrl &= timer->irq_ack_mask;
0493     tctrl &= ~GPTIMER_TCTRL_RS;
0494     tctrl |= GPTIMER_TCTRL_LD | GPTIMER_TCTRL_EN;
0495     if ( once == 0 )
0496         tctrl |= GPTIMER_TCTRL_RS; /* Restart Timer */
0497     grlib_store_32(&timer->tregs->tctrl, tctrl);
0498 }
0499 
0500 static void gptimer_tlib_stop(struct tlib_dev *hand)
0501 {
0502     struct gptimer_timer_priv *timer = (struct gptimer_timer_priv *)hand;
0503     uint32_t tctrl;
0504 
0505     /* Load the selected Frequency */
0506     tctrl = grlib_load_32(&timer->tregs->tctrl);
0507     tctrl &= ~(GPTIMER_TCTRL_EN|GPTIMER_TCTRL_IP);
0508     grlib_store_32(&timer->tregs->tctrl, tctrl);
0509 }
0510 
0511 static void gptimer_tlib_restart(struct tlib_dev *hand)
0512 {
0513     struct gptimer_timer_priv *timer = (struct gptimer_timer_priv *)hand;
0514     uint32_t tctrl;
0515 
0516     tctrl = grlib_load_32(&timer->tregs->tctrl);
0517     tctrl |= GPTIMER_TCTRL_LD | GPTIMER_TCTRL_EN;
0518     grlib_store_32(&timer->tregs->tctrl, tctrl);
0519 }
0520 
0521 static void gptimer_tlib_get_counter(
0522     struct tlib_dev *hand,
0523     unsigned int *counter)
0524 {
0525     struct gptimer_timer_priv *timer = (struct gptimer_timer_priv *)hand;
0526 
0527     *counter = grlib_load_32(&timer->tregs->tcntval);
0528 }
0529 
0530 static void gptimer_tlib_get_widthmask(
0531     struct tlib_dev *hand,
0532     unsigned int *widthmask)
0533 {
0534     struct gptimer_timer_priv *timer = (struct gptimer_timer_priv *)hand;
0535     struct gptimer_priv *priv = priv_from_timer(timer);
0536 
0537     *widthmask = priv->widthmask;
0538 }
0539 
0540 static struct tlib_drv gptimer_tlib_drv =
0541 {
0542     .reset = gptimer_tlib_reset,
0543     .get_freq = gptimer_tlib_get_freq,
0544     .set_freq = gptimer_tlib_set_freq,
0545     .irq_reg = gptimer_tlib_irq_reg,
0546     .irq_unreg = gptimer_tlib_irq_unreg,
0547     .start = gptimer_tlib_start,
0548     .stop = gptimer_tlib_stop,
0549     .restart = gptimer_tlib_restart,
0550     .get_counter = gptimer_tlib_get_counter,
0551     .custom = NULL,
0552     .int_pend = gptimer_tlib_int_pend,
0553     .get_widthmask = gptimer_tlib_get_widthmask,
0554 };