File indexing completed on 2025-05-11 08:24:07
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
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
0041 #define STATIC static
0042
0043
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
0057
0058
0059
0060 struct l4stat_regs {
0061 unsigned int cval[32];
0062 unsigned int cctrl[32];
0063 unsigned int cmax[32];
0064 unsigned int timestamp;
0065 };
0066
0067 struct l4stat_priv {
0068 struct drvmgr_dev *dev;
0069
0070
0071 struct l4stat_regs *regs;
0072
0073
0074 char devname[9];
0075
0076 int ncpu;
0077 int ncnt;
0078
0079
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
0090 #ifdef DEBUG
0091 #define L4STAT_BAD_CMD "N/A. Wrong event"
0092 STATIC const char *l4stat_event_names[] = {
0093 "Instruction cache miss",
0094 "Instruction MMU TLB miss",
0095 "Instruction cache hold",
0096 "Instruction MMU hold",
0097 L4STAT_BAD_CMD,
0098 L4STAT_BAD_CMD,
0099 L4STAT_BAD_CMD,
0100 L4STAT_BAD_CMD,
0101 "Data cache (read) miss",
0102 "Data MMU TLB miss",
0103 "Data cache hold",
0104 "Data MMU hold",
0105 L4STAT_BAD_CMD,
0106 L4STAT_BAD_CMD,
0107 L4STAT_BAD_CMD,
0108 L4STAT_BAD_CMD,
0109 "Data write buffer hold",
0110 "Total instruction count",
0111 "Integer instruction count",
0112 "Floating-point unit instruction count",
0113 "Branch prediction miss",
0114 "Execution time, exluding debug mode",
0115 L4STAT_BAD_CMD,
0116 "AHB utilization (per AHB master)",
0117 "AHB utilization (total)",
0118 L4STAT_BAD_CMD,
0119 L4STAT_BAD_CMD,
0120 L4STAT_BAD_CMD,
0121 L4STAT_BAD_CMD,
0122 L4STAT_BAD_CMD,
0123 L4STAT_BAD_CMD,
0124 L4STAT_BAD_CMD,
0125 L4STAT_BAD_CMD,
0126 L4STAT_BAD_CMD,
0127 "Integer branches",
0128 L4STAT_BAD_CMD,
0129 L4STAT_BAD_CMD,
0130 L4STAT_BAD_CMD,
0131 L4STAT_BAD_CMD,
0132 L4STAT_BAD_CMD,
0133 "CALL instructions",
0134 L4STAT_BAD_CMD,
0135 L4STAT_BAD_CMD,
0136 L4STAT_BAD_CMD,
0137 L4STAT_BAD_CMD,
0138 L4STAT_BAD_CMD,
0139 L4STAT_BAD_CMD,
0140 L4STAT_BAD_CMD,
0141 "Regular type 2 instructions",
0142 L4STAT_BAD_CMD,
0143 L4STAT_BAD_CMD,
0144 L4STAT_BAD_CMD,
0145 L4STAT_BAD_CMD,
0146 L4STAT_BAD_CMD,
0147 L4STAT_BAD_CMD,
0148 L4STAT_BAD_CMD,
0149 "LOAD and STORE instructions",
0150 "LOAD instructions",
0151 "STORE instructions",
0152 L4STAT_BAD_CMD,
0153 L4STAT_BAD_CMD,
0154 L4STAT_BAD_CMD,
0155 L4STAT_BAD_CMD,
0156 L4STAT_BAD_CMD,
0157 "AHB IDLE cycles",
0158 "AHB BUSY cycles",
0159 "AHB Non-Seq. transfers",
0160 "AHB Seq. transfers",
0161 "AHB read accesses",
0162 "AHB write accesses",
0163 "AHB byte accesses",
0164 "AHB half-word accesses",
0165 "AHB word accesses",
0166 "AHB double word accesses",
0167 "AHB quad word accesses",
0168 "AHB eight word accesses",
0169 "AHB waitstates",
0170 "AHB RETRY responses",
0171 "AHB SPLIT responses",
0172 "AHB SPLIT delay",
0173 "AHB bus locked",
0174 L4STAT_BAD_CMD,
0175 L4STAT_BAD_CMD,
0176 L4STAT_BAD_CMD,
0177 L4STAT_BAD_CMD,
0178 L4STAT_BAD_CMD,
0179 L4STAT_BAD_CMD,
0180 L4STAT_BAD_CMD,
0181 L4STAT_BAD_CMD,
0182 L4STAT_BAD_CMD,
0183 L4STAT_BAD_CMD,
0184 L4STAT_BAD_CMD,
0185 L4STAT_BAD_CMD,
0186 L4STAT_BAD_CMD,
0187 L4STAT_BAD_CMD,
0188 L4STAT_BAD_CMD,
0189 "external event 0",
0190 "external event 1",
0191 "external event 2",
0192 "external event 3",
0193 "external event 4",
0194 "external event 5",
0195 "external event 6",
0196 "external event 7",
0197 "external event 8",
0198 "external event 9",
0199 "external event 10",
0200 "external event 11",
0201 "external event 12",
0202 "external event 13",
0203 "external event 14",
0204 "external event 15",
0205 "AHB IDLE cycles (2)",
0206 "AHB BUSY cycles (2)",
0207 "AHB Non-Seq. transfers (2)",
0208 "AHB Seq. transfers (2)",
0209 "AHB read accesses (2)",
0210 "AHB write accesses (2)",
0211 "AHB byte accesses (2)",
0212 "AHB half-word accesses (2)",
0213 "AHB word accesses (2)",
0214 "AHB double word accesses (2)",
0215 "AHB quad word accesses (2)",
0216 "AHB eight word accesses (2)",
0217 "AHB waitstates (2)",
0218 "AHB RETRY responses (2)",
0219 "AHB SPLIT responses (2)",
0220 "AHB SPLIT delay (2)",
0221 "PMC: master 0 has grant",
0222 "PMC: master 1 has grant",
0223 "PMC: master 2 has grant",
0224 "PMC: master 3 has grant",
0225 "PMC: master 4 has grant",
0226 "PMC: master 5 has grant",
0227 "PMC: master 6 has grant",
0228 "PMC: master 7 has grant",
0229 "PMC: master 8 has grant",
0230 "PMC: master 9 has grant",
0231 "PMC: master 10 has grant",
0232 "PMC: master 11 has grant",
0233 "PMC: master 12 has grant",
0234 "PMC: master 13 has grant",
0235 "PMC: master 14 has grant",
0236 "PMC: master 15 has grant",
0237 "PMC: master 0 lacks grant",
0238 "PMC: master 1 lacks grant",
0239 "PMC: master 2 lacks grant",
0240 "PMC: master 3 lacks grant",
0241 "PMC: master 4 lacks grant",
0242 "PMC: master 5 lacks grant",
0243 "PMC: master 6 lacks grant",
0244 "PMC: master 7 lacks grant",
0245 "PMC: master 8 lacks grant",
0246 "PMC: master 9 lacks grant",
0247 "PMC: master 10 lacks grant",
0248 "PMC: master 11 lacks grant",
0249 "PMC: master 12 lacks grant",
0250 "PMC: master 13 lacks grant",
0251 "PMC: master 14 lacks grant",
0252 "PMC: master 15 lacks grant",
0253 ""
0254 };
0255 #endif
0256
0257
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}
0275 };
0276
0277 struct amba_drv_info l4stat_drv_info =
0278 {
0279 {
0280 DRVMGR_OBJ_DRV,
0281 NULL,
0282 NULL,
0283 DRIVER_AMBAPP_GAISLER_L4STAT_ID,
0284 "L4STAT_DRV",
0285 DRVMGR_BUS_TYPE_AMBAPP,
0286 &l4stat_ops,
0287 NULL,
0288 0,
0289 sizeof(struct l4stat_priv),
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
0308 apb = ainfo->info.apb_slv;
0309
0310
0311 dev_id = ainfo->id.device;
0312
0313
0314 if (apb->common.ver != 0) {
0315 DBG("L4STAT rev 0 only supported.\n");
0316 return L4STAT_ERR_ERROR;
0317 }
0318
0319
0320 priv->regs = (struct l4stat_regs *)apb->start;
0321
0322 DBG("L4STAT regs 0x%08x\n", (unsigned int) priv->regs);
0323
0324
0325 tmp = REG_READ(&priv->regs->cctrl[0]);
0326
0327
0328
0329
0330
0331
0332
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
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
0376 if (l4stat_init(priv) != L4STAT_ERR_OK) {
0377 return DRVMGR_FAIL;
0378 }
0379
0380
0381
0382
0383
0384
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
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
0449 ctrl = (options & ~(CCTRL_EVENTID | CCTRL_CPUAHBM));
0450
0451 ctrl = (ctrl | ((event << CCTRL_EVENTID_BIT) & CCTRL_EVENTID));
0452
0453 ctrl = (ctrl | ((cpu << CCTRL_CPUAHBM_BIT) & CCTRL_CPUAHBM));
0454
0455 ctrl = (ctrl | CCTRL_EN);
0456
0457 REG_WRITE(&priv->regs->cctrl[counter], ctrl);
0458
0459
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
0481 REG_WRITE(&priv->regs->cctrl[counter], 0);
0482
0483
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
0627 val = REG_READ(&priv->regs->cval[counter]);
0628
0629
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
0639 DBG("L4STAT COUNTER[%d], Event: %s, Count: %d [0x%08x]\n",
0640 counter, l4stat_event_names[event],val,val);
0641 #endif
0642
0643 return L4STAT_ERR_OK;
0644 }
0645