File indexing completed on 2025-05-11 08:24:06
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 <bsp.h>
0032 #include <grlib/ambapp.h>
0033 #include <grlib/grascs.h>
0034 #include <grlib/grlib.h>
0035
0036 #include <grlib/grlib_impl.h>
0037
0038 #ifndef GAISLER_ASCS
0039 #define GAISLER_ASCS 0x043
0040 #endif
0041
0042 #ifdef DEBUG
0043 #define DBG(x...) printk(x)
0044 #else
0045 #define DBG(x...)
0046 #endif
0047
0048 typedef struct {
0049 volatile unsigned int cmd;
0050 volatile unsigned int clk;
0051 volatile unsigned int sts;
0052 volatile unsigned int tcd;
0053 volatile unsigned int tmd;
0054 } GRASCS_regs;
0055
0056 typedef struct {
0057 unsigned char tmconf;
0058 unsigned char usconf;
0059 unsigned char nslaves;
0060 unsigned char dbits;
0061 int clkfreq;
0062 } GRASCS_caps;
0063
0064 typedef struct {
0065 GRASCS_regs *regs;
0066 GRASCS_caps *caps;
0067 rtems_id tcsem1, tcsem2;
0068 rtems_id tmsem1, tmsem2;
0069 volatile char running;
0070 int tcptr;
0071 int tmptr;
0072 int tcwords;
0073 int tmwords;
0074 } GRASCS_cfg;
0075
0076 static GRASCS_cfg *cfg = NULL;
0077
0078
0079
0080
0081
0082
0083
0084
0085
0086
0087
0088
0089
0090 static int ASCS_get_addr(int *base, int *irq) {
0091
0092 struct ambapp_apb_info core;
0093
0094 if(ambapp_find_apbslv(ambapp_plb(), VENDOR_GAISLER, GAISLER_ASCS, &core) == 1) {
0095 *base = core.start;
0096 *irq = core.common.irq;
0097 DBG("ASCS_get_addr: Registerd ASCS core at 0x%x with irq %i\n",core.start, core.irq);
0098 return 0;
0099 }
0100 DBG("ASCS_get_addr: Failed to detect core\n");
0101 return -1;
0102 }
0103
0104
0105
0106
0107
0108
0109
0110
0111 static int ASCS_calc_clkreg(int sysfreq, int etrfreq) {
0112
0113 if(cfg->caps->usconf)
0114 return 1000000/etrfreq;
0115 else
0116 return sysfreq*1000/etrfreq;
0117 }
0118
0119
0120
0121
0122
0123
0124 static int ASCS_get_sysfreq(void) {
0125
0126 struct ambapp_apb_info gpt;
0127 struct gptimer_regs *tregs;
0128 int tmp;
0129
0130 if(ambapp_find_apbslv(ambapp_plb(), VENDOR_GAISLER, GAISLER_GPTIMER, &gpt) == 1) {
0131 tregs = (struct gptimer_regs *) gpt.start;
0132 tmp = (tregs->scaler_reload + 1)*1000;
0133 DBG("ASCS_get_sysfreq: Detected system frequency %i kHz\n",tmp);
0134 if((tmp < GRASCS_MIN_SFREQ) || (tmp > GRASCS_MAX_SFREQ)) {
0135 DBG("ASCS_get_sysfreq: System frequency is invalid for ASCS core\n");
0136 return -1;
0137 }
0138 else
0139 return (tregs->scaler_reload + 1)*1000;
0140 }
0141 DBG("ASCS_get_sysfreq: Failed to detect system frequency\n");
0142 return -1;
0143 }
0144
0145
0146
0147
0148
0149
0150
0151
0152 static rtems_isr ASCS_irqhandler(void *v) {
0153
0154 if(cfg->regs->sts & GRASCS_STS_TCDONE) {
0155
0156 cfg->regs->sts |= GRASCS_STS_TCDONE;
0157
0158 if(--cfg->tcwords == 0)
0159
0160 rtems_semaphore_release(cfg->tcsem2);
0161 else {
0162
0163 if(cfg->caps->dbits == 8) {
0164 cfg->tcptr++;
0165 cfg->regs->tcd = *((unsigned char*)cfg->tcptr);
0166 }
0167 else if(cfg->caps->dbits == 16) {
0168 cfg->tcptr += 2;
0169 cfg->regs->tcd = *((unsigned short int*)cfg->tcptr);
0170 }
0171 else {
0172 cfg->tcptr += 4;
0173 cfg->regs->tcd = *((unsigned int*)cfg->tcptr);
0174 }
0175 }
0176 }
0177
0178 if(cfg->regs->sts & GRASCS_STS_TMDONE) {
0179
0180 cfg->regs->sts |= GRASCS_STS_TMDONE;
0181
0182
0183 if(cfg->caps->dbits == 8) {
0184 *((unsigned char*)cfg->tmptr) = (unsigned char)(cfg->regs->tmd & 0xFF);
0185 cfg->tmptr++;
0186 }
0187 else if(cfg->caps->dbits == 16) {
0188 *((unsigned short int*)cfg->tmptr) = (unsigned short int)(cfg->regs->tmd & 0xFFFF);
0189 cfg->tmptr += 2;
0190 }
0191 else {
0192 *((unsigned int*)cfg->tmptr) = cfg->regs->tmd;
0193 cfg->tmptr += 4;
0194 }
0195
0196 if(--cfg->tmwords == 0)
0197
0198 rtems_semaphore_release(cfg->tmsem2);
0199 else
0200
0201 cfg->regs->cmd |= GRASCS_CMD_SENDTM;
0202 }
0203 }
0204
0205
0206
0207
0208
0209
0210
0211
0212
0213
0214 int ASCS_init(void) {
0215
0216 int base, irq, tmp;
0217
0218 DBG("ASCS_init: Starting initialization of ASCS core\n");
0219
0220
0221 if((cfg = grlib_malloc(sizeof(*cfg))) == NULL) {
0222 DBG("ASCS_init: Could not allocate memory for cfg struc\n");
0223 return -1;
0224 }
0225
0226 if((cfg->caps = grlib_calloc(1,sizeof(*cfg->caps))) == NULL) {
0227 DBG("ASCS_init: Could not allocate memory for caps struc\n");
0228 goto init_error1;
0229 }
0230
0231
0232 if(rtems_semaphore_create(rtems_build_name('A','S','C','0'),1,
0233 (RTEMS_FIFO|RTEMS_SIMPLE_BINARY_SEMAPHORE|
0234 RTEMS_NO_INHERIT_PRIORITY|RTEMS_LOCAL|
0235 RTEMS_NO_PRIORITY_CEILING), 0,
0236 &cfg->tcsem1) != RTEMS_SUCCESSFUL) {
0237 DBG("ASCS_init: Failed to create semaphore ASC0\n");
0238 goto init_error2;
0239 }
0240 if(rtems_semaphore_create(rtems_build_name('A','S','C','1'),1,
0241 (RTEMS_FIFO|RTEMS_SIMPLE_BINARY_SEMAPHORE|
0242 RTEMS_NO_INHERIT_PRIORITY|RTEMS_LOCAL|
0243 RTEMS_NO_PRIORITY_CEILING), 0,
0244 &cfg->tmsem1) != RTEMS_SUCCESSFUL) {
0245 DBG("ASCS_init: Failed to create semaphore ASC1\n");
0246 goto init_error2;
0247 }
0248
0249 if(rtems_semaphore_create(rtems_build_name('A','S','C','2'),0,
0250 (RTEMS_FIFO|RTEMS_SIMPLE_BINARY_SEMAPHORE|
0251 RTEMS_NO_INHERIT_PRIORITY|RTEMS_LOCAL|
0252 RTEMS_NO_PRIORITY_CEILING), 0,
0253 &cfg->tcsem2) != RTEMS_SUCCESSFUL) {
0254 DBG("ASCS_init: Failed to create semaphore ASC2\n");
0255 goto init_error2;
0256 }
0257 if(rtems_semaphore_create(rtems_build_name('A','S','C','3'),0,
0258 (RTEMS_FIFO|RTEMS_SIMPLE_BINARY_SEMAPHORE|
0259 RTEMS_NO_INHERIT_PRIORITY|RTEMS_LOCAL|
0260 RTEMS_NO_PRIORITY_CEILING), 0,
0261 &cfg->tmsem2) != RTEMS_SUCCESSFUL) {
0262 DBG("ASCS_init: Failed to create semaphore ASC3\n");
0263 goto init_error2;
0264 }
0265
0266
0267 if(ASCS_get_addr(&base, &irq) == -1)
0268 goto init_error2;
0269
0270 cfg->regs = (GRASCS_regs*)base;
0271
0272
0273 tmp = cfg->regs->sts;
0274 cfg->caps->dbits = ((tmp >> GRASCS_STS_DBITS_BITS) & 0x1F) + 1;
0275 cfg->caps->nslaves = ((tmp >> GRASCS_STS_NSLAVES_BITS) & 0xF) + 1;
0276 cfg->caps->tmconf = (tmp >> GRASCS_STS_TMCONF_BITS) & 0x1;
0277 cfg->caps->usconf = (tmp >> GRASCS_STS_USCONF_BITS) & 0x1;
0278
0279
0280 cfg->running = 0;
0281 cfg->regs->cmd |= GRASCS_CMD_RESET;
0282 if((tmp = ASCS_get_sysfreq()) == -1)
0283 goto init_error2;
0284 cfg->caps->clkfreq = tmp;
0285 while(ASCS_iface_status())
0286 ;
0287 cfg->regs->clk = ASCS_calc_clkreg(tmp, GRASCS_DEFAULT_ETRFREQ);
0288 cfg->regs->cmd = GRASCS_CMD_US1C;
0289 cfg->regs->cmd |= (tmp/1000 << GRASCS_CMD_US1_BITS) | GRASCS_CMD_US1C |
0290 GRASCS_CMD_TCDONE | GRASCS_CMD_TMDONE;
0291
0292
0293 rtems_interrupt_handler_install(irq, "grascs",
0294 RTEMS_INTERRUPT_SHARED,
0295 ASCS_irqhandler, NULL);
0296
0297 return 0;
0298
0299 init_error2:
0300 free(cfg->caps);
0301 init_error1:
0302 free(cfg);
0303 return -1;
0304 }
0305
0306
0307
0308
0309
0310
0311
0312
0313
0314
0315
0316
0317 int ASCS_input_select(int slave) {
0318
0319 if((slave < 0) || (slave > cfg->caps->nslaves)) {
0320
0321 DBG("ASCS_input_select: Wrong slave number\n");
0322 return -GRASCS_ERROR_CAPFAULT;
0323 }
0324
0325 if(rtems_semaphore_obtain(cfg->tmsem1,RTEMS_NO_WAIT,RTEMS_NO_TIMEOUT) !=
0326 RTEMS_SUCCESSFUL) {
0327
0328 DBG("ASCS_input_select: Transaction active\n");
0329 return -GRASCS_ERROR_TRANSACTIVE;
0330 }
0331
0332 cfg->regs->cmd = ((cfg->regs->cmd & ~GRASCS_CMD_SLAVESEL) |
0333 (slave << GRASCS_CMD_SLAVESEL_BITS));
0334
0335 rtems_semaphore_release(cfg->tmsem1);
0336 return 0;
0337 }
0338
0339
0340
0341
0342
0343
0344
0345
0346
0347
0348
0349
0350
0351 int ASCS_etr_select(int etr, int freq) {
0352
0353 if((etr < 0) || (etr > GRASCS_MAX_TMS) || ((cfg->caps->tmconf == 0) && (etr > 0)) ||
0354 (freq < GRASCS_MIN_ETRFREQ) || (freq > GRASCS_MAX_ETRFREQ)) {
0355
0356 DBG("ASCS_etr_select: Wrong etr src number or wrong frequency\n");
0357 return -GRASCS_ERROR_CAPFAULT;
0358 }
0359
0360 if(cfg->regs->sts & GRASCS_STS_ERUNNING) {
0361
0362 DBG("ASCS_etr_select: Synch interface is running\n");
0363 return -GRASCS_ERROR_STARTSTOP;
0364 }
0365
0366 cfg->regs->clk = ASCS_calc_clkreg(cfg->caps->clkfreq,freq);
0367 cfg->regs->cmd = ((cfg->regs->cmd & ~GRASCS_CMD_ETRCTRL) |
0368 (etr << GRASCS_CMD_ETRCTRL_BITS));
0369
0370 return 0;
0371 }
0372
0373
0374
0375
0376
0377
0378 void ASCS_start(void) {
0379
0380
0381 cfg->regs->cmd |= GRASCS_CMD_STARTSTOP;
0382 cfg->running = 1;
0383 }
0384
0385
0386
0387
0388
0389
0390
0391
0392
0393 void ASCS_stop(void) {
0394
0395
0396 cfg->running = 0;
0397
0398
0399
0400
0401 rtems_semaphore_obtain(cfg->tcsem1,RTEMS_WAIT,RTEMS_NO_TIMEOUT);
0402 rtems_semaphore_obtain(cfg->tmsem1,RTEMS_WAIT,RTEMS_NO_TIMEOUT);
0403
0404
0405 cfg->regs->cmd &= ~GRASCS_CMD_STARTSTOP;
0406
0407
0408 rtems_semaphore_release(cfg->tcsem1);
0409 rtems_semaphore_release(cfg->tmsem1);
0410 }
0411
0412
0413
0414
0415
0416
0417
0418
0419
0420
0421 int ASCS_iface_status(void) {
0422
0423 return ((cfg->regs->sts & 0x3) & (0x2 | cfg->running));
0424 }
0425
0426
0427
0428
0429
0430
0431
0432
0433 int ASCS_TC_send(int *word) {
0434
0435 int retval;
0436
0437 if(rtems_semaphore_obtain(cfg->tcsem1,RTEMS_NO_WAIT,RTEMS_NO_TIMEOUT) !=
0438 RTEMS_SUCCESSFUL) {
0439
0440
0441 DBG("ASCS_TC_send: Could not obtain semaphore, transcation probably in progress\n");
0442 return -GRASCS_ERROR_TRANSACTIVE;
0443 }
0444
0445 if(!cfg->running) {
0446
0447 DBG("ASCS_TC_send: Serial interface is not started\n");
0448 retval = -GRASCS_ERROR_STARTSTOP;
0449 }
0450 else {
0451
0452 cfg->tcwords = 1;
0453 if(cfg->caps->dbits == 8)
0454 cfg->regs->tcd = *((unsigned char*)word);
0455 else if(cfg->caps->dbits == 16)
0456 cfg->regs->tcd = *((unsigned short int*)((int)word & ~1));
0457 else
0458 cfg->regs->tcd = *((unsigned int*)((int)word & ~3));
0459
0460
0461 rtems_semaphore_obtain(cfg->tcsem2,RTEMS_WAIT,RTEMS_NO_TIMEOUT);
0462 retval = 0;
0463 }
0464
0465 rtems_semaphore_release(cfg->tcsem1);
0466
0467 return retval;
0468 }
0469
0470
0471
0472
0473
0474
0475
0476
0477
0478
0479
0480
0481
0482
0483
0484 int ASCS_TC_send_block(int *block, int ntrans) {
0485
0486 int retval;
0487
0488 if(rtems_semaphore_obtain(cfg->tcsem1,RTEMS_NO_WAIT,RTEMS_NO_TIMEOUT) !=
0489 RTEMS_SUCCESSFUL) {
0490
0491
0492 DBG("ASCS_TC_send_block: Could not obtain semaphore, transcation probably in progress\n");
0493 return -GRASCS_ERROR_TRANSACTIVE;
0494 }
0495
0496 if(!cfg->running) {
0497
0498 DBG("ASCS_TC_send_block: Serial interface is not started\n");
0499 retval = -GRASCS_ERROR_STARTSTOP;
0500 }
0501 else {
0502
0503 cfg->tcwords = ntrans;
0504 if(cfg->caps->dbits == 8) {
0505 cfg->tcptr = (int)block;
0506 cfg->regs->tcd = *((unsigned char*)cfg->tcptr);
0507 }
0508 else if(cfg->caps->dbits == 16) {
0509 cfg->tcptr = (int)block & ~1;
0510 cfg->regs->tcd = *((unsigned short int*)cfg->tcptr);
0511 }
0512 else {
0513 cfg->tcptr = (int)block & ~3;
0514 cfg->regs->tcd = *((unsigned int*)cfg->tcptr);
0515 }
0516
0517
0518 rtems_semaphore_obtain(cfg->tcsem2,RTEMS_WAIT,RTEMS_NO_TIMEOUT);
0519 retval = 0;
0520 }
0521
0522 rtems_semaphore_release(cfg->tcsem1);
0523
0524 return retval;
0525 }
0526
0527
0528
0529
0530
0531
0532
0533
0534
0535
0536
0537 void ASCS_TC_sync_start(void) {
0538
0539 cfg->regs->cmd |= GRASCS_CMD_ESTARTSTOP;
0540 }
0541
0542
0543
0544
0545
0546
0547
0548
0549
0550 void ASCS_TC_sync_stop(void) {
0551
0552 cfg->regs->cmd &= ~GRASCS_CMD_ESTARTSTOP;
0553 }
0554
0555
0556
0557
0558
0559
0560
0561
0562
0563 int ASCS_TM_recv(int *word) {
0564
0565 int retval;
0566
0567 if(rtems_semaphore_obtain(cfg->tmsem1,RTEMS_NO_WAIT,RTEMS_NO_TIMEOUT) !=
0568 RTEMS_SUCCESSFUL) {
0569
0570
0571 DBG("ASCS_TM_recv: Could not obtain semaphore, transaction probably in progress\n");
0572 return -GRASCS_ERROR_TRANSACTIVE;
0573 }
0574
0575 if(!cfg->running) {
0576
0577 DBG("ASCS_TM_recv: Serial interface is not started\n");
0578 retval = -GRASCS_ERROR_STARTSTOP;
0579 }
0580 else {
0581
0582 cfg->tmwords = 1;
0583 cfg->tmptr = (int)word;
0584 cfg->regs->cmd |= GRASCS_CMD_SENDTM;
0585
0586
0587 rtems_semaphore_obtain(cfg->tmsem2,RTEMS_WAIT,RTEMS_NO_TIMEOUT);
0588 retval = 0;
0589 }
0590
0591 rtems_semaphore_release(cfg->tmsem1);
0592
0593 return retval;
0594 }
0595
0596
0597
0598
0599
0600
0601
0602
0603
0604
0605
0606
0607
0608
0609 int ASCS_TM_recv_block(int *block, int ntrans) {
0610
0611 int retval;
0612
0613 if(rtems_semaphore_obtain(cfg->tmsem1,RTEMS_NO_WAIT,RTEMS_NO_TIMEOUT) !=
0614 RTEMS_SUCCESSFUL) {
0615
0616
0617 DBG("ASCS_TM_recv_block: Could not obtain semaphore, transaction probably in progress\n");
0618 return -GRASCS_ERROR_TRANSACTIVE;
0619 }
0620
0621 if(!cfg->running) {
0622
0623 DBG("ASCS_TM_recv_block: Serial interface is not started\n");
0624 retval = -GRASCS_ERROR_STARTSTOP;
0625 }
0626 else {
0627
0628 cfg->tmwords = ntrans;
0629 cfg->tmptr = (int)block;
0630 cfg->regs->cmd |= GRASCS_CMD_SENDTM;
0631
0632
0633 rtems_semaphore_obtain(cfg->tmsem2,RTEMS_WAIT,RTEMS_NO_TIMEOUT);
0634 retval = 0;
0635 }
0636
0637 rtems_semaphore_release(cfg->tmsem1);
0638
0639 return retval;
0640 }