File indexing completed on 2025-05-11 08:24:05
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 <stdlib.h>
0031 #include <string.h>
0032 #include <drvmgr/drvmgr.h>
0033 #include <grlib/ambapp_bus.h>
0034
0035 #include <grlib/gr1553b.h>
0036 #include <grlib/gr1553bm.h>
0037
0038 #include <grlib/grlib_impl.h>
0039
0040 #define GR1553BM_WRITE_MEM(adr, val) *(volatile uint32_t *)(adr) = (uint32_t)(val)
0041 #define GR1553BM_READ_MEM(adr) (*(volatile uint32_t *)(adr))
0042
0043 #define GR1553BM_WRITE_REG(adr, val) *(volatile uint32_t *)(adr) = (uint32_t)(val)
0044 #define GR1553BM_READ_REG(adr) (*(volatile uint32_t *)(adr))
0045
0046 struct gr1553bm_priv {
0047 struct drvmgr_dev **pdev;
0048 struct gr1553b_regs *regs;
0049 SPIN_DECLARE(devlock);
0050
0051 void *buffer;
0052 unsigned int buffer_base_hw;
0053 unsigned int buffer_base;
0054 unsigned int buffer_end;
0055 unsigned int buffer_size;
0056 unsigned int read_pos;
0057 int started;
0058 struct gr1553bm_config cfg;
0059
0060
0061 volatile uint64_t time;
0062 };
0063
0064 void gr1553bm_isr(void *data);
0065
0066
0067 struct gr1553bm_config gr1553bm_default_config =
0068 {
0069
0070 .time_resolution = 0,
0071 .time_ovf_irq = 1,
0072
0073
0074 .filt_error_options = GR1553BM_ERROPTS_ALL,
0075 .filt_rtadr = 0xffffffff,
0076 .filt_subadr = 0xffffffff,
0077 .filt_mc = 0x0007ffff,
0078
0079
0080 .buffer_size = 128*1024,
0081 .buffer_custom = NULL,
0082 };
0083
0084 void gr1553bm_register(void)
0085 {
0086
0087 gr1553_register();
0088 }
0089
0090 static void gr1553bm_hw_start(struct gr1553bm_priv *priv)
0091 {
0092 SPIN_IRQFLAGS(irqflags);
0093
0094
0095 SPIN_LOCK_IRQ(&priv->devlock, irqflags);
0096
0097 priv->started = 1;
0098
0099
0100 priv->regs->irq = GR1553B_IRQ_BMD | GR1553B_IRQ_BMTOF;
0101
0102
0103 if ( priv->cfg.time_ovf_irq ) {
0104 priv->regs->imask |= GR1553B_IRQEN_BMDE | GR1553B_IRQEN_BMTOE;
0105 } else {
0106 priv->regs->imask |= GR1553B_IRQEN_BMDE;
0107 }
0108
0109
0110 priv->regs->bm_ctrl =
0111 (priv->cfg.filt_error_options &
0112 (GR1553B_BM_CTRL_MANL|GR1553B_BM_CTRL_UDWL|GR1553B_BM_CTRL_IMCL))
0113 | GR1553B_BM_CTRL_BMEN;
0114
0115 SPIN_UNLOCK_IRQ(&priv->devlock, irqflags);
0116 }
0117
0118 static void gr1553bm_hw_stop(struct gr1553bm_priv *priv)
0119 {
0120 SPIN_IRQFLAGS(irqflags);
0121
0122 SPIN_LOCK_IRQ(&priv->devlock, irqflags);
0123
0124
0125 priv->regs->bm_ctrl = 0;
0126
0127
0128 priv->regs->imask &= ~(GR1553B_IRQEN_BMDE|GR1553B_IRQEN_BMTOE);
0129
0130
0131 priv->regs->irq = GR1553B_IRQ_BMD | GR1553B_IRQ_BMTOF;
0132
0133 priv->started = 0;
0134
0135 SPIN_UNLOCK_IRQ(&priv->devlock, irqflags);
0136 }
0137
0138
0139 void *gr1553bm_open(int minor)
0140 {
0141 struct drvmgr_dev **pdev = NULL;
0142 struct gr1553bm_priv *priv = NULL;
0143 struct amba_dev_info *ambadev;
0144 struct ambapp_core *pnpinfo;
0145
0146
0147 pdev = gr1553_bm_open(minor);
0148 if ( pdev == NULL )
0149 goto fail;
0150
0151 priv = grlib_calloc(1, sizeof(*priv));
0152 if ( priv == NULL )
0153 goto fail;
0154
0155
0156 priv->pdev = pdev;
0157 (*pdev)->priv = priv;
0158
0159
0160 ambadev = (struct amba_dev_info *)(*pdev)->businfo;
0161 pnpinfo = &ambadev->info;
0162 priv->regs = (struct gr1553b_regs *)pnpinfo->apb_slv->start;
0163 SPIN_INIT(&priv->devlock, "gr1553bm");
0164
0165
0166 priv->cfg = gr1553bm_default_config;
0167
0168
0169 gr1553bm_hw_stop(priv);
0170
0171 return priv;
0172
0173 fail:
0174 if ( pdev )
0175 gr1553_bm_close(pdev);
0176 return NULL;
0177 }
0178
0179
0180 void gr1553bm_close(void *bm)
0181 {
0182 struct gr1553bm_priv *priv = bm;
0183
0184 if ( priv->started ) {
0185 gr1553bm_stop(bm);
0186 }
0187
0188 if ( (priv->cfg.buffer_custom == NULL) && priv->buffer )
0189 free(priv->buffer);
0190
0191 gr1553_bm_close(priv->pdev);
0192 free(priv);
0193 }
0194
0195
0196 int gr1553bm_config(void *bm, struct gr1553bm_config *cfg)
0197 {
0198 int retval = 0;
0199 struct gr1553bm_priv *priv = bm;
0200
0201 if ( priv->started )
0202 return -1;
0203
0204
0205
0206
0207
0208 if ( (priv->cfg.buffer_custom == NULL) && priv->buffer ) {
0209 free(priv->buffer);
0210 priv->buffer = NULL;
0211 }
0212 priv->buffer_size = cfg->buffer_size & ~0x7;
0213 if ((unsigned int)cfg->buffer_custom & 1) {
0214
0215
0216
0217 priv->buffer = (void*)((unsigned int)cfg->buffer_custom & ~1);
0218 priv->buffer_base_hw = (unsigned int)priv->buffer;
0219 drvmgr_translate_check(
0220 *priv->pdev,
0221 DMAMEM_TO_CPU,
0222 (void *)priv->buffer_base_hw,
0223 (void **)&priv->buffer_base,
0224 priv->buffer_size);
0225 } else {
0226 if (cfg->buffer_custom == NULL) {
0227
0228 priv->buffer = grlib_malloc(priv->buffer_size + 8);
0229 if (priv->buffer == NULL) {
0230 retval = -1;
0231 goto err;
0232 }
0233
0234 priv->buffer_base = ((unsigned int)priv->buffer + (8-1)) & ~(8-1);
0235 } else {
0236
0237
0238
0239 priv->buffer = cfg->buffer_custom;
0240 priv->buffer_base = (unsigned int)priv->buffer;
0241 }
0242
0243
0244
0245 drvmgr_translate_check(
0246 *priv->pdev,
0247 CPUMEM_TO_DMA,
0248 (void *)priv->buffer_base,
0249 (void **)&priv->buffer_base_hw,
0250 priv->buffer_size);
0251
0252 }
0253
0254
0255 if (priv->buffer_base_hw & (8-1)) {
0256 retval = -2;
0257 goto err;
0258 }
0259
0260
0261 priv->cfg = *cfg;
0262
0263 err:
0264 if (retval) {
0265 if (cfg->buffer_custom == NULL && priv->buffer) {
0266 free(priv->buffer);
0267 }
0268 priv->buffer_base_hw = (unsigned int)NULL;
0269 priv->buffer_base = (unsigned int)NULL;
0270 priv->buffer = NULL;
0271 }
0272 return retval;
0273 }
0274
0275
0276 int gr1553bm_start(void *bm)
0277 {
0278 struct gr1553bm_priv *priv = bm;
0279
0280 if ( priv->started )
0281 return -1;
0282 if ( priv->buffer == NULL )
0283 return -2;
0284
0285
0286 priv->regs->bm_ttag =
0287 priv->cfg.time_resolution << GR1553B_BM_TTAG_RES_BIT;
0288
0289
0290 priv->regs->bm_adr = priv->cfg.filt_rtadr;
0291 priv->regs->bm_subadr = priv->cfg.filt_subadr;
0292 priv->regs->bm_mc = priv->cfg.filt_mc;
0293
0294
0295 priv->regs->bm_start = priv->buffer_base_hw;
0296 priv->regs->bm_end = priv->buffer_base_hw + priv->cfg.buffer_size - 4;
0297 priv->regs->bm_pos = priv->buffer_base_hw;
0298 priv->read_pos = priv->buffer_base;
0299 priv->buffer_end = priv->buffer_base + priv->cfg.buffer_size;
0300
0301
0302 if (drvmgr_interrupt_register(*priv->pdev, 0, "gr1553bm", gr1553bm_isr, priv))
0303 return -3;
0304
0305
0306 gr1553bm_hw_start(priv);
0307
0308 return 0;
0309 }
0310
0311
0312 void gr1553bm_stop(void *bm)
0313 {
0314 struct gr1553bm_priv *priv = bm;
0315
0316
0317 gr1553bm_hw_stop(priv);
0318
0319
0320
0321
0322
0323
0324 drvmgr_interrupt_unregister(*priv->pdev, 0, gr1553bm_isr, priv);
0325 }
0326
0327 int gr1553bm_started(void *bm)
0328 {
0329 return ((struct gr1553bm_priv *)bm)->started;
0330 }
0331
0332
0333
0334
0335
0336 void gr1553bm_time(void *bm, uint64_t *time)
0337 {
0338 struct gr1553bm_priv *priv = bm;
0339 unsigned int hwtime, hwtime2;
0340
0341 resample:
0342 if ( priv->started && (priv->cfg.time_ovf_irq == 0) ) {
0343
0344
0345
0346
0347
0348
0349
0350
0351 if ( priv->regs->irq & GR1553B_IRQ_BMTOF ) {
0352
0353 priv->regs->irq = GR1553B_IRQ_BMTOF;
0354 priv->time += (GR1553B_BM_TTAG_VAL + 1);
0355 }
0356 }
0357
0358
0359 hwtime = priv->regs->bm_ttag & GR1553B_BM_TTAG_VAL;
0360 if ( time )
0361 *time = priv->time | hwtime;
0362
0363 if ( priv->cfg.time_ovf_irq ) {
0364
0365 hwtime2 = priv->regs->bm_ttag & GR1553B_BM_TTAG_VAL;
0366 if ( hwtime > hwtime2 ) {
0367
0368
0369
0370
0371 goto resample;
0372 }
0373 }
0374 }
0375
0376
0377 int gr1553bm_available(void *bm, int *nentries)
0378 {
0379 struct gr1553bm_priv *priv = bm;
0380 unsigned int top, bot, pos;
0381
0382 if ( !priv->started )
0383 return -1;
0384
0385
0386 pos = priv->regs->bm_pos;
0387
0388
0389 pos = priv->buffer_base + (pos - priv->buffer_base_hw);
0390
0391 if ( pos >= priv->read_pos ) {
0392 top = (pos - priv->read_pos)/sizeof(struct gr1553bm_entry);
0393 bot = 0;
0394 } else {
0395 top = (priv->buffer_end - priv->read_pos)/sizeof(struct gr1553bm_entry);
0396 bot = (pos - priv->buffer_base)/sizeof(struct gr1553bm_entry);
0397 }
0398
0399 if ( nentries )
0400 *nentries = top+bot;
0401
0402 return 0;
0403 }
0404
0405
0406 int gr1553bm_read(void *bm, struct gr1553bm_entry *dst, int *max)
0407 {
0408 struct gr1553bm_priv *priv = bm;
0409 unsigned int dest, pos, left, newPos, len;
0410 unsigned int topAdr, botAdr, topLen, botLen;
0411
0412 if ( !priv || !priv->started )
0413 return -1;
0414
0415 left = *max;
0416 pos = priv->regs->bm_pos & ~0x7;
0417
0418
0419 pos = priv->buffer_base + (pos - priv->buffer_base_hw);
0420
0421 if ( (pos == priv->read_pos) || (left < 1) ) {
0422
0423 *max = 0;
0424 return 0;
0425 }
0426 newPos = 0;
0427
0428
0429 if ( pos >= priv->read_pos ) {
0430
0431 topAdr = priv->read_pos;
0432 botAdr = 0;
0433 topLen = (pos - priv->read_pos)/sizeof(struct gr1553bm_entry);
0434 botLen = 0;
0435 } else {
0436
0437 topAdr = priv->read_pos;
0438 botAdr = priv->buffer_base;
0439 topLen = (priv->buffer_end - priv->read_pos)/sizeof(struct gr1553bm_entry);
0440 botLen = (pos - priv->buffer_base)/sizeof(struct gr1553bm_entry);
0441 }
0442
0443 dest = (unsigned int)dst;
0444 if ( topLen > 0 ) {
0445
0446 if ( topLen > left ) {
0447 len = left;
0448 left = 0;
0449 } else {
0450 len = topLen;
0451 left -= topLen;
0452 }
0453 newPos = topAdr + (len * sizeof(struct gr1553bm_entry));
0454 if ( newPos >= priv->buffer_end )
0455 newPos -= priv->buffer_size;
0456 if ( priv->cfg.copy_func ) {
0457 dest += priv->cfg.copy_func(
0458 dest,
0459 (void *)topAdr,
0460 len,
0461 priv->cfg.copy_func_arg
0462 );
0463 } else {
0464 memcpy( (void *)dest,
0465 (void *)topAdr,
0466 len * sizeof(struct gr1553bm_entry));
0467 dest += len * sizeof(struct gr1553bm_entry);
0468 }
0469 }
0470
0471 if ( (botLen > 0) && (left > 0) ) {
0472
0473 if ( botLen > left ) {
0474 len = left;
0475 left = 0;
0476 } else {
0477 len = botLen;
0478 left -= botLen;
0479 }
0480 newPos = botAdr + (len * sizeof(struct gr1553bm_entry));
0481
0482 if ( priv->cfg.copy_func ) {
0483 priv->cfg.copy_func(
0484 dest,
0485 (void *)botAdr,
0486 len,
0487 priv->cfg.copy_func_arg
0488 );
0489 } else {
0490 memcpy( (void *)dest,
0491 (void *)botAdr,
0492 len * sizeof(struct gr1553bm_entry));
0493 }
0494 }
0495
0496
0497
0498 priv->read_pos = newPos;
0499
0500
0501 *max = *max - left;
0502
0503 return 0;
0504 }
0505
0506
0507
0508
0509 void gr1553bm_isr(void *data)
0510 {
0511 struct gr1553bm_priv *priv = data;
0512 uint32_t irqflag;
0513
0514
0515 irqflag = priv->regs->irq & (GR1553B_IRQ_BMD | GR1553B_IRQ_BMTOF);
0516
0517
0518 if ( (irqflag == 0) || (priv->started == 0) )
0519 return;
0520
0521 if ( (irqflag & GR1553B_IRQ_BMTOF) && priv->cfg.time_ovf_irq ) {
0522
0523 priv->time += (GR1553B_BM_TTAG_VAL + 1);
0524
0525
0526 priv->regs->irq = GR1553B_IRQ_BMTOF;
0527 }
0528
0529 if ( irqflag & GR1553B_IRQ_BMD ) {
0530
0531
0532
0533
0534
0535
0536 priv->regs->irq = GR1553B_IRQ_BMD;
0537
0538 if ( priv->cfg.dma_error_isr )
0539 priv->cfg.dma_error_isr(data, priv->cfg.dma_error_arg);
0540
0541 gr1553bm_hw_stop(priv);
0542 }
0543 }