Back to home page

LXR

 
 

    


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

0001 /* SPDX-License-Identifier: BSD-2-Clause */
0002 
0003 /* L4STAT APB-Register Driver.
0004  *
0005  * COPYRIGHT (c) 2017.
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 <rtems.h>
0031 #include <rtems/libio.h>
0032 #include <stdio.h>
0033 #include <bsp.h>
0034 #include <rtems/bspIo.h> /* printk */
0035 
0036 #include <drvmgr/drvmgr.h>
0037 #include <grlib/ambapp_bus.h>
0038 #include <grlib/l4stat.h>
0039 
0040 /*#define STATIC*/
0041 #define STATIC static
0042 
0043 /*#define DEBUG 1*/
0044 
0045 #ifdef DEBUG
0046 #define DBG(x...) printf(x)
0047 #else
0048 #define DBG(x...) 
0049 #endif
0050 
0051 #define REG_WRITE(addr, val) (*(volatile unsigned int *)(addr) = (unsigned int)(val))
0052 #define REG_READ(addr) (*(volatile unsigned int *)(addr))
0053 
0054 
0055 /*
0056  * L4STAT CCTRL register fields
0057  * DEFINED IN HEADER file
0058  */
0059 
0060 struct l4stat_regs {
0061     unsigned int cval[32];              /* 0x000 */
0062     unsigned int cctrl[32];             /* 0x080 */
0063     unsigned int cmax[32];              /* 0x100 */
0064     unsigned int timestamp;             /* 0x180 */
0065 };
0066 
0067 struct l4stat_priv {
0068     struct drvmgr_dev *dev;
0069 
0070     /* L4STAT control registers */
0071     struct l4stat_regs *regs;
0072 
0073     /* L4STAT driver register */
0074     char devname[9];
0075 
0076     int ncpu;
0077     int ncnt;
0078 
0079     /* L4stat capabilities */
0080     int max_count_support;
0081     int internalahb_event_support;
0082     int dsu_event_support;
0083     int external_event_support;
0084     int ahbtrace_event_support;
0085 };
0086 
0087 STATIC struct l4stat_priv *l4statpriv = NULL;
0088 
0089 /* Event names */
0090 #ifdef DEBUG
0091 #define L4STAT_BAD_CMD "N/A. Wrong event"
0092 STATIC const char *l4stat_event_names[] = {
0093     "Instruction cache miss",               /* 0x00 */
0094     "Instruction MMU TLB miss",             /* 0x01 */
0095     "Instruction cache hold",               /* 0x02 */
0096     "Instruction MMU hold",                 /* 0x03 */
0097     L4STAT_BAD_CMD,                     /* 0x04 */
0098     L4STAT_BAD_CMD,                     /* 0x05 */
0099     L4STAT_BAD_CMD,                     /* 0x06 */
0100     L4STAT_BAD_CMD,                     /* 0x07 */
0101     "Data cache (read) miss",               /* 0x08 */
0102     "Data MMU TLB miss",                    /* 0x09 */
0103     "Data cache hold",                  /* 0x0a */
0104     "Data MMU hold",                    /* 0x0b */
0105     L4STAT_BAD_CMD,                     /* 0x0c */
0106     L4STAT_BAD_CMD,                     /* 0x0d */
0107     L4STAT_BAD_CMD,                     /* 0x0e */
0108     L4STAT_BAD_CMD,                     /* 0x0f */
0109     "Data write buffer hold",               /* 0x10 */
0110     "Total instruction count",              /* 0x11 */
0111     "Integer instruction count",                /* 0x12 */
0112     "Floating-point unit instruction count",        /* 0x13 */
0113     "Branch prediction miss",               /* 0x14 */
0114     "Execution time, exluding debug mode",          /* 0x15 */
0115     L4STAT_BAD_CMD,                     /* 0x16 */
0116     "AHB utilization (per AHB master)",         /* 0x17 */
0117     "AHB utilization (total)",              /* 0x18 */
0118     L4STAT_BAD_CMD,                     /* 0x19 */
0119     L4STAT_BAD_CMD,                     /* 0x1a */
0120     L4STAT_BAD_CMD,                     /* 0x1b */
0121     L4STAT_BAD_CMD,                     /* 0x1c */
0122     L4STAT_BAD_CMD,                     /* 0x1d */
0123     L4STAT_BAD_CMD,                     /* 0x1e */
0124     L4STAT_BAD_CMD,                     /* 0x1f */
0125     L4STAT_BAD_CMD,                     /* 0x20 */
0126     L4STAT_BAD_CMD,                     /* 0x21 */
0127     "Integer branches",                 /* 0x22 */
0128     L4STAT_BAD_CMD,                     /* 0x23 */
0129     L4STAT_BAD_CMD,                     /* 0x24 */
0130     L4STAT_BAD_CMD,                     /* 0x25 */
0131     L4STAT_BAD_CMD,                     /* 0x26 */
0132     L4STAT_BAD_CMD,                     /* 0x27 */
0133     "CALL instructions",                    /* 0x28 */
0134     L4STAT_BAD_CMD,                     /* 0x29 */
0135     L4STAT_BAD_CMD,                     /* 0x2a */
0136     L4STAT_BAD_CMD,                     /* 0x2b */
0137     L4STAT_BAD_CMD,                     /* 0x2c */
0138     L4STAT_BAD_CMD,                     /* 0x2d */
0139     L4STAT_BAD_CMD,                     /* 0x2e */
0140     L4STAT_BAD_CMD,                     /* 0x2f */
0141     "Regular type 2 instructions",              /* 0x30 */
0142     L4STAT_BAD_CMD,                     /* 0x31 */
0143     L4STAT_BAD_CMD,                     /* 0x32 */
0144     L4STAT_BAD_CMD,                     /* 0x33 */
0145     L4STAT_BAD_CMD,                     /* 0x34 */
0146     L4STAT_BAD_CMD,                     /* 0x35 */
0147     L4STAT_BAD_CMD,                     /* 0x36 */
0148     L4STAT_BAD_CMD,                     /* 0x37 */
0149     "LOAD and STORE instructions",              /* 0x38 */
0150     "LOAD instructions",                    /* 0x39 */
0151     "STORE instructions",                   /* 0x3a */
0152     L4STAT_BAD_CMD,                     /* 0x3b */
0153     L4STAT_BAD_CMD,                     /* 0x3c */
0154     L4STAT_BAD_CMD,                     /* 0x3d */
0155     L4STAT_BAD_CMD,                     /* 0x3e */
0156     L4STAT_BAD_CMD,                     /* 0x3f */
0157     "AHB IDLE cycles",                  /* 0x40 */
0158     "AHB BUSY cycles",                  /* 0x41 */
0159     "AHB Non-Seq. transfers",               /* 0x42 */
0160     "AHB Seq. transfers",                   /* 0x43 */
0161     "AHB read accesses",                    /* 0x44 */
0162     "AHB write accesses",                   /* 0x45 */
0163     "AHB byte accesses",                    /* 0x46 */
0164     "AHB half-word accesses",               /* 0x47 */
0165     "AHB word accesses",                    /* 0x48 */
0166     "AHB double word accesses",             /* 0x49 */
0167     "AHB quad word accesses",               /* 0x4A */
0168     "AHB eight word accesses",              /* 0x4B */
0169     "AHB waitstates",                   /* 0x4C */
0170     "AHB RETRY responses",                  /* 0x4D */
0171     "AHB SPLIT responses",                  /* 0x4E */
0172     "AHB SPLIT delay",                  /* 0x4F */
0173     "AHB bus locked",                   /* 0x50 */
0174     L4STAT_BAD_CMD,                     /* 0x51 */
0175     L4STAT_BAD_CMD,                     /* 0x52 */
0176     L4STAT_BAD_CMD,                     /* 0x53 */
0177     L4STAT_BAD_CMD,                     /* 0x54 */
0178     L4STAT_BAD_CMD,                     /* 0x55 */
0179     L4STAT_BAD_CMD,                     /* 0x56 */
0180     L4STAT_BAD_CMD,                     /* 0x57 */
0181     L4STAT_BAD_CMD,                     /* 0x58 */
0182     L4STAT_BAD_CMD,                     /* 0x59 */
0183     L4STAT_BAD_CMD,                     /* 0x5a */
0184     L4STAT_BAD_CMD,                     /* 0x5b */
0185     L4STAT_BAD_CMD,                     /* 0x5c */
0186     L4STAT_BAD_CMD,                     /* 0x5d */
0187     L4STAT_BAD_CMD,                     /* 0x5e */
0188     L4STAT_BAD_CMD,                     /* 0x5f */
0189     "external event 0",                 /* 0x60 */
0190     "external event 1",                 /* 0x61 */
0191     "external event 2",                 /* 0x62 */
0192     "external event 3",                 /* 0x63 */
0193     "external event 4",                 /* 0x64 */
0194     "external event 5",                 /* 0x65 */
0195     "external event 6",                 /* 0x66 */
0196     "external event 7",                 /* 0x67 */
0197     "external event 8",                 /* 0x68 */
0198     "external event 9",                 /* 0x69 */
0199     "external event 10",                    /* 0x6A */
0200     "external event 11",                    /* 0x6B */
0201     "external event 12",                    /* 0x6C */
0202     "external event 13",                    /* 0x6D */
0203     "external event 14",                    /* 0x6E */
0204     "external event 15",                    /* 0x6F */
0205     "AHB IDLE cycles (2)",                  /* 0x70 */
0206     "AHB BUSY cycles (2)",                  /* 0x71 */
0207     "AHB Non-Seq. transfers (2)",               /* 0x72 */
0208     "AHB Seq. transfers (2)",               /* 0x73 */
0209     "AHB read accesses (2)",                /* 0x74 */
0210     "AHB write accesses (2)",               /* 0x75 */
0211     "AHB byte accesses (2)",                /* 0x76 */
0212     "AHB half-word accesses (2)",               /* 0x77 */
0213     "AHB word accesses (2)",                /* 0x78 */
0214     "AHB double word accesses (2)",             /* 0x79 */
0215     "AHB quad word accesses (2)",               /* 0x7A */
0216     "AHB eight word accesses (2)",              /* 0x7B */
0217     "AHB waitstates (2)",                   /* 0x7C */
0218     "AHB RETRY responses (2)",              /* 0x7D */
0219     "AHB SPLIT responses (2)",              /* 0x7E */
0220     "AHB SPLIT delay (2)",                  /* 0x7F */
0221     "PMC: master 0 has grant",              /* 0x80 */
0222     "PMC: master 1 has grant",              /* 0x81 */
0223     "PMC: master 2 has grant",              /* 0x82 */
0224     "PMC: master 3 has grant",              /* 0x83 */
0225     "PMC: master 4 has grant",              /* 0x84 */
0226     "PMC: master 5 has grant",              /* 0x85 */
0227     "PMC: master 6 has grant",              /* 0x86 */
0228     "PMC: master 7 has grant",              /* 0x87 */
0229     "PMC: master 8 has grant",              /* 0x88 */
0230     "PMC: master 9 has grant",              /* 0x89 */
0231     "PMC: master 10 has grant",             /* 0x8A */
0232     "PMC: master 11 has grant",             /* 0x8B */
0233     "PMC: master 12 has grant",             /* 0x8C */
0234     "PMC: master 13 has grant",             /* 0x8D */
0235     "PMC: master 14 has grant",             /* 0x8E */
0236     "PMC: master 15 has grant",             /* 0x8F */
0237     "PMC: master 0 lacks grant",                /* 0x90 */
0238     "PMC: master 1 lacks grant",                /* 0x91 */
0239     "PMC: master 2 lacks grant",                /* 0x92 */
0240     "PMC: master 3 lacks grant",                /* 0x93 */
0241     "PMC: master 4 lacks grant",                /* 0x94 */
0242     "PMC: master 5 lacks grant",                /* 0x95 */
0243     "PMC: master 6 lacks grant",                /* 0x96 */
0244     "PMC: master 7 lacks grant",                /* 0x97 */
0245     "PMC: master 8 lacks grant",                /* 0x98 */
0246     "PMC: master 9 lacks grant",                /* 0x99 */
0247     "PMC: master 10 lacks grant",               /* 0x9A */
0248     "PMC: master 11 lacks grant",               /* 0x9B */
0249     "PMC: master 12 lacks grant",               /* 0x9C */
0250     "PMC: master 13 lacks grant",               /* 0x9D */
0251     "PMC: master 14 lacks grant",               /* 0x9E */
0252     "PMC: master 15 lacks grant",               /* 0x9F */
0253     ""
0254 };
0255 #endif /* DEBUG */
0256 
0257 /* Driver prototypes */
0258 
0259 STATIC int l4stat_init(struct l4stat_priv *priv);
0260 
0261 int l4stat_init1(struct drvmgr_dev *dev);
0262 
0263 struct drvmgr_drv_ops l4stat_ops = 
0264 {
0265     .init = {l4stat_init1, NULL, NULL, NULL},
0266     .remove = NULL,
0267     .info = NULL
0268 };
0269 
0270 struct amba_dev_id l4stat_ids[] = 
0271 {
0272     {VENDOR_GAISLER, GAISLER_L4STAT},
0273     {VENDOR_GAISLER, GAISLER_L3STAT},
0274     {0, 0}      /* Mark end of table */
0275 };
0276 
0277 struct amba_drv_info l4stat_drv_info =
0278 {
0279     {
0280         DRVMGR_OBJ_DRV,         /* Driver */
0281         NULL,               /* Next driver */
0282         NULL,               /* Device list */
0283         DRIVER_AMBAPP_GAISLER_L4STAT_ID,/* Driver ID */
0284         "L4STAT_DRV",           /* Driver Name */
0285         DRVMGR_BUS_TYPE_AMBAPP,     /* Bus Type */
0286         &l4stat_ops,
0287         NULL,               /* Funcs */
0288         0,              /* No devices yet */
0289         sizeof(struct l4stat_priv), /* Let DRVMGR allocate for us */
0290     },
0291     &l4stat_ids[0],
0292 };
0293 
0294 void l4stat_register_drv (void)
0295 {
0296     DBG("Registering L4STAT driver\n");
0297     drvmgr_drv_register(&l4stat_drv_info.general);
0298 }
0299 
0300 STATIC int l4stat_init(struct l4stat_priv *priv)
0301 {
0302     struct ambapp_apb_info *apb;
0303     struct amba_dev_info *ainfo = priv->dev->businfo;
0304     unsigned int tmp;
0305     unsigned short dev_id;
0306 
0307     /* Find L4STAT core from Plug&Play information */
0308     apb = ainfo->info.apb_slv;
0309 
0310     /* Check if L4STAT or L3STAT core from Plug&Play information */
0311     dev_id = ainfo->id.device;
0312 
0313     /* Check if rev 1 of core (only rev 0 supported) */
0314     if (apb->common.ver != 0) {
0315         DBG("L4STAT rev 0 only supported.\n");
0316         return L4STAT_ERR_ERROR;
0317     }
0318 
0319     /* Found L4STAT core, init private structure */
0320     priv->regs = (struct l4stat_regs *)apb->start;
0321 
0322     DBG("L4STAT regs 0x%08x\n", (unsigned int) priv->regs);
0323 
0324     /* Find L4STAT capabilities */
0325     tmp = REG_READ(&priv->regs->cctrl[0]);
0326     /* The CPU field in the register is just information of the
0327      * cpus that are connected to the stat unit, but it is not
0328      * really used for anything else. I can still have more masters
0329      * on the bus (e.g. IOMMU) that I can collect stats from,
0330      * so it makes no sense to limit the cpus to the actual cpus.
0331      * Therefore, I will take the maximum number as 16. */
0332     /*priv->ncpu = ((tmp & CCTRL_NCPU) >> CCTRL_NCPU_BIT) + 1;*/
0333     priv->ncpu = 16;
0334     if (dev_id == GAISLER_L3STAT) {
0335         priv->ncnt = ((tmp & CCTRL_NCNT_L3STAT) >> CCTRL_NCNT_BIT) + 1;
0336     }else{
0337         priv->ncnt = ((tmp & CCTRL_NCNT) >> CCTRL_NCNT_BIT) + 1;
0338     }
0339     priv->max_count_support = (tmp & CCTRL_MC) >> CCTRL_MC_BIT;
0340     priv->internalahb_event_support = (tmp & CCTRL_IA) >> CCTRL_IA_BIT;
0341     priv->dsu_event_support = (tmp & CCTRL_DS) >> CCTRL_DS_BIT;
0342     priv->external_event_support = (tmp & CCTRL_EE) >> CCTRL_EE_BIT;
0343     priv->ahbtrace_event_support = (tmp & CCTRL_AE) >> CCTRL_AE_BIT;
0344 
0345     /* DEBUG print */
0346     DBG("L4STAT with following capabilities:\n");
0347     DBG(" -NCPU: %d, NCNT: %d, MaxCNT: %s\n", priv->ncpu, priv->ncnt, 
0348             (priv->max_count_support?"Available":"N/A"));
0349     DBG(" -Events= InternalAHB: %s, DSU: %s, External: %s, AHBTRACE: %s\n",
0350             (priv->internalahb_event_support?"Available":"N/A"),
0351             (priv->dsu_event_support?"Available":"N/A"),
0352             (priv->external_event_support?"Available":"N/A"),
0353             (priv->ahbtrace_event_support?"Available":"N/A"));
0354 
0355     return L4STAT_ERR_OK;
0356 }
0357 
0358 int l4stat_init1(struct drvmgr_dev *dev)
0359 {
0360     struct l4stat_priv *priv = dev->priv;
0361 
0362     DBG("L4STAT[%d] on bus %s\n", dev->minor_drv, dev->parent->dev->name);
0363 
0364     if (l4statpriv) {
0365         DBG("Driver only supports one L4STAT core\n");
0366         return DRVMGR_FAIL;
0367     }
0368 
0369     if (priv == NULL) {
0370         return DRVMGR_NOMEM;
0371     }
0372     priv->dev = dev;
0373     l4statpriv = priv;
0374 
0375     /* Initilize driver struct */
0376     if (l4stat_init(priv) != L4STAT_ERR_OK) {
0377         return DRVMGR_FAIL;
0378     }
0379 
0380     /* Startup Action:
0381      *  - None
0382      */
0383 
0384     /* Device name */
0385     sprintf(priv->devname, "l4stat0");
0386 
0387     return DRVMGR_OK;
0388 }
0389 
0390 int l4stat_counter_enable(unsigned int counter, int event, int cpu, int options)
0391 {
0392     struct l4stat_priv *priv = l4statpriv;
0393     unsigned int ctrl;
0394 
0395     if (priv == NULL) {
0396         DBG("L4STAT Device not initialized\n");
0397         return L4STAT_ERR_EINVAL;
0398     }
0399 
0400     if (counter >= priv->ncnt) {
0401         DBG("L4STAT Wrong counter\n");
0402         return L4STAT_ERR_EINVAL;
0403     }
0404 
0405     if ((cpu < 0) || (cpu >= priv->ncpu)) {
0406         DBG("L4STAT Wrong cpu\n");
0407         return L4STAT_ERR_EINVAL;
0408     }
0409 
0410     if ((options & L4STAT_OPTIONS_MAXIMUM_DURATION) || 
0411             (options & L4STAT_OPTIONS_EVENT_LEVEL_ENABLE)) {
0412         if (priv->max_count_support == 0) {
0413             DBG("L4STAT maximum duration count not supported\n");
0414             return L4STAT_ERR_IMPLEMENTED;
0415         }
0416     }
0417 
0418     /* Check event is supported */
0419     if ((event < 0) || (event >= 0x80)) {
0420         DBG("L4STAT Wrong event\n");
0421         return L4STAT_ERR_EINVAL;
0422     }
0423     if ((event == 0x18) || (event == 0x17)) {
0424         if (priv->internalahb_event_support == 0) {
0425             DBG("L4STAT internal ahb event not supported\n");
0426             return L4STAT_ERR_IMPLEMENTED;
0427         }
0428     }
0429     if ((event >= 0x40) && (event < 0x60)) {
0430         if (priv->dsu_event_support == 0) {
0431             DBG("L4STAT dsu event not supported\n");
0432             return L4STAT_ERR_IMPLEMENTED;
0433         }
0434     }
0435     if ((event >= 0x60) && (event < 0x70)) {
0436         if (priv->external_event_support == 0) {
0437             DBG("L4STAT external event not supported\n");
0438             return L4STAT_ERR_IMPLEMENTED;
0439         }
0440     }
0441     if ((event >= 0x70) && (event < 0x80)) {
0442         if (priv->ahbtrace_event_support == 0) {
0443             DBG("L4STAT ahbtrace event not supported\n");
0444             return L4STAT_ERR_IMPLEMENTED;
0445         }
0446     }
0447 
0448     /* Prepare counter control */
0449     ctrl = (options & ~(CCTRL_EVENTID | CCTRL_CPUAHBM));
0450     /* Put event id */
0451     ctrl = (ctrl | ((event << CCTRL_EVENTID_BIT) & CCTRL_EVENTID));
0452     /* Put cpu id */
0453     ctrl = (ctrl | ((cpu << CCTRL_CPUAHBM_BIT) & CCTRL_CPUAHBM));
0454     /* Enable counter */
0455     ctrl = (ctrl | CCTRL_EN);
0456 
0457     REG_WRITE(&priv->regs->cctrl[counter], ctrl);
0458 
0459     /* DEBUG print */
0460     DBG("L4STAT COUNTER[%d] enabled with event: %s, cpu: %d\n", counter, 
0461             l4stat_event_names[event],cpu);
0462 
0463     return L4STAT_ERR_OK;
0464 }
0465 
0466 int l4stat_counter_disable(unsigned int counter)
0467 {
0468     struct l4stat_priv *priv = l4statpriv;
0469 
0470     if (priv == NULL) {
0471         DBG("L4STAT Device not initialized\n");
0472         return L4STAT_ERR_EINVAL;
0473     }
0474 
0475     if (counter >= priv->ncnt) {
0476         DBG("L4STAT Wrong counter\n");
0477         return L4STAT_ERR_EINVAL;
0478     }
0479 
0480     /* Disable counter */
0481     REG_WRITE(&priv->regs->cctrl[counter], 0);
0482 
0483     /* DEBUG print */
0484     DBG("L4STAT COUNTER[%d] disabled\n", counter);
0485 
0486     return L4STAT_ERR_OK;
0487 }
0488 
0489 int l4stat_counter_get(unsigned int counter, uint32_t * val)
0490 {
0491     struct l4stat_priv *priv = l4statpriv;
0492 
0493     if (priv == NULL) {
0494         DBG("L4STAT Device not initialized\n");
0495         return L4STAT_ERR_EINVAL;
0496     }
0497 
0498     if (counter >= priv->ncnt) {
0499         DBG("L4STAT Wrong counter\n");
0500         return L4STAT_ERR_EINVAL;
0501     }
0502 
0503     if (val == NULL) {
0504         DBG("L4STAT Wrong pointer\n");
0505         return L4STAT_ERR_EINVAL;
0506     }
0507 
0508     *val = REG_READ(&priv->regs->cval[counter]);
0509 
0510     return L4STAT_ERR_OK;
0511 }
0512 
0513 int l4stat_counter_set(unsigned int counter, uint32_t val)
0514 {
0515     struct l4stat_priv *priv = l4statpriv;
0516 
0517     if (priv == NULL) {
0518         DBG("L4STAT Device not initialized\n");
0519         return L4STAT_ERR_EINVAL;
0520     }
0521 
0522     if (counter >= priv->ncnt) {
0523         DBG("L4STAT Wrong counter\n");
0524         return L4STAT_ERR_EINVAL;
0525     }
0526 
0527     REG_WRITE(&priv->regs->cval[counter],val);
0528 
0529     return L4STAT_ERR_OK;
0530 }
0531 
0532 int l4stat_counter_max_get(unsigned int counter, uint32_t * val)
0533 {
0534     struct l4stat_priv *priv = l4statpriv;
0535 
0536     if (priv == NULL) {
0537         DBG("L4STAT Device not initialized\n");
0538         return L4STAT_ERR_EINVAL;
0539     }
0540 
0541     if (counter >= priv->ncnt) {
0542         DBG("L4STAT Wrong counter\n");
0543         return L4STAT_ERR_EINVAL;
0544     }
0545 
0546     if (val == NULL) {
0547         DBG("L4STAT Wrong pointer\n");
0548         return L4STAT_ERR_EINVAL;
0549     }
0550 
0551     *val = REG_READ(&priv->regs->cmax[counter]);
0552 
0553     return L4STAT_ERR_OK;
0554 }
0555 
0556 int l4stat_counter_max_set(unsigned int counter, uint32_t val)
0557 {
0558     struct l4stat_priv *priv = l4statpriv;
0559 
0560     if (priv == NULL) {
0561         DBG("L4STAT Device not initialized\n");
0562         return L4STAT_ERR_EINVAL;
0563     }
0564 
0565     if (counter >= priv->ncnt) {
0566         DBG("L4STAT Wrong counter\n");
0567         return L4STAT_ERR_EINVAL;
0568     }
0569 
0570     REG_WRITE(&priv->regs->cmax[counter],val);
0571 
0572     return L4STAT_ERR_OK;
0573 }
0574 
0575 int l4stat_tstamp_get(uint32_t * val)
0576 {
0577     struct l4stat_priv *priv = l4statpriv;
0578 
0579     if (priv == NULL) {
0580         DBG("L4STAT Device not initialized\n");
0581         return L4STAT_ERR_EINVAL;
0582     }
0583 
0584     if (val == NULL) {
0585         DBG("L4STAT Wrong pointer\n");
0586         return L4STAT_ERR_EINVAL;
0587     }
0588 
0589     *val = REG_READ(&priv->regs->timestamp);
0590 
0591     return L4STAT_ERR_OK;
0592 }
0593 
0594 int l4stat_tstamp_set(uint32_t val)
0595 {
0596     struct l4stat_priv *priv = l4statpriv;
0597 
0598     if (priv == NULL) {
0599         DBG("L4STAT Device not initialized\n");
0600         return L4STAT_ERR_EINVAL;
0601     }
0602 
0603     REG_WRITE(&priv->regs->timestamp,val);
0604 
0605     return L4STAT_ERR_OK;
0606 }
0607 
0608 int l4stat_counter_print(unsigned int counter)
0609 {
0610 #ifdef DEBUG
0611     struct l4stat_priv *priv = l4statpriv;
0612     unsigned int val;
0613     unsigned int ctrl;
0614     unsigned int event;
0615 
0616     if (priv == NULL) {
0617         DBG("L4STAT Device not initialized\n");
0618         return L4STAT_ERR_EINVAL;
0619     }
0620 
0621     if (counter >= priv->ncnt) {
0622         DBG("L4STAT Wrong counter\n");
0623         return L4STAT_ERR_EINVAL;
0624     }
0625 
0626     /* Get counter val*/
0627     val = REG_READ(&priv->regs->cval[counter]);
0628 
0629     /* Get counter info*/
0630     ctrl = REG_READ(&priv->regs->cctrl[counter]);
0631     if ((ctrl & CCTRL_EN) == 0) {
0632         DBG("L4STAT COUNTER[%d] disabled\n", counter);
0633         return L4STAT_ERR_OK;
0634     }
0635 
0636     event = (ctrl & CCTRL_EVENTID) >> CCTRL_EVENTID_BIT;
0637 
0638     /* DEBUG print */
0639     DBG("L4STAT COUNTER[%d], Event: %s, Count: %d [0x%08x]\n", 
0640         counter, l4stat_event_names[event],val,val);
0641 #endif /* DEBUG */
0642 
0643     return L4STAT_ERR_OK;
0644 }
0645