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
0031 #include <bsp.h>
0032 #include <stdlib.h>
0033 #include <stdio.h>
0034 #include <string.h>
0035 #include <assert.h>
0036 #include <ctype.h>
0037 #include <rtems/bspIo.h>
0038
0039 #include <grlib/grcan.h>
0040 #include <grlib/canbtrs.h>
0041 #include <drvmgr/drvmgr.h>
0042 #include <grlib/ambapp_bus.h>
0043 #include <grlib/ambapp.h>
0044
0045 #include <grlib/grlib_impl.h>
0046 #include "grcan_internal.h"
0047
0048
0049
0050 #define DBG_TX 2
0051 #define DBG_RX 4
0052 #define DBG_STATE 8
0053
0054 #define DEBUG_FLAGS (DBG_STATE | DBG_RX | DBG_TX )
0055
0056
0057
0058
0059 #include <grlib/debug_defs.h>
0060
0061
0062
0063 struct grcanfd_bd0 {
0064 uint32_t head[2];
0065 uint64_t data0;
0066 };
0067
0068 struct grcanfd_bd1 {
0069 unsigned long long data[2];
0070 };
0071
0072 static uint8_t dlc2len[16] = {
0073 0, 1, 2, 3,
0074 4, 5, 6, 7,
0075 8, 12, 16, 20,
0076 24, 32, 48, 64
0077 };
0078
0079 static uint8_t len2fddlc[14] = {
0080 0x9,
0081 0xA,
0082 0xB,
0083 0xC,
0084 -1,
0085 0xD,
0086 -1,
0087 -1,
0088 -1,
0089 0xE,
0090 -1,
0091 -1,
0092 -1,
0093 0xF,
0094 };
0095
0096
0097 static inline uint8_t grcan_len2dlc(int len)
0098 {
0099 if (len <= 8)
0100 return len;
0101 if (len > 64)
0102 return -1;
0103 if (len & 0x3)
0104 return -1;
0105 return len2fddlc[(len - 12) >> 2];
0106 }
0107
0108 static inline int grcan_numbds(int len)
0109 {
0110 return 1 + ((len + 7) >> 4);
0111 }
0112
0113 static int grcan_hw_read_try_fd(
0114 struct grcan_priv *pDev,
0115 struct grcan_regs *regs,
0116 CANFDMsg * buffer,
0117 int max)
0118 {
0119 int j;
0120 CANFDMsg *dest;
0121 struct grcanfd_bd0 *source, tmp, *rxmax;
0122 unsigned int wp, rp, size, addr;
0123 int bds_hw_avail, bds_tot, bds, ret, dlc;
0124 uint64_t *dp;
0125 SPIN_IRQFLAGS(oldLevel);
0126
0127 FUNCDBG();
0128
0129 wp = READ_REG(®s->rx0wr);
0130 rp = READ_REG(®s->rx0rd);
0131
0132
0133
0134
0135
0136
0137
0138
0139 if (wp != rp) {
0140
0141
0142
0143 size = READ_REG(®s->rx0size);
0144
0145
0146 bds_hw_avail = grcan_hw_rxavail(rp, wp, size);
0147
0148 addr = (unsigned int)pDev->rx;
0149 source = (struct grcanfd_bd0 *)(addr + rp);
0150 dest = buffer;
0151 rxmax = (struct grcanfd_bd0 *)(addr + size);
0152 ret = bds_tot = 0;
0153
0154
0155 while ((ret < max) && (bds_tot < bds_hw_avail)) {
0156
0157 *(uint64_t *)&tmp = READ_DMA_DOUBLE(source);
0158 if (tmp.head[1] & 0x4) {
0159 DBGC(DBG_RX, "overrun\n");
0160 }
0161 if (tmp.head[1] & 0x2) {
0162 DBGC(DBG_RX, "bus-off mode\n");
0163 }
0164 if (tmp.head[1] & 0x1) {
0165 DBGC(DBG_RX, "error-passive mode\n");
0166 }
0167
0168 dest->extended = tmp.head[0] >> 31;
0169 dest->rtr = (tmp.head[0] >> 30) & 0x1;
0170 if (dest->extended) {
0171 dest->id = tmp.head[0] & 0x3fffffff;
0172 } else {
0173 dest->id = (tmp.head[0] >> 18) & 0xfff;
0174 }
0175 dest->fdopts = (tmp.head[1] >> 25) & GRCAN_FDMASK;
0176 dlc = tmp.head[1] >> 28;
0177 if (dest->fdopts & GRCAN_FDOPT_FDFRM) {
0178 dest->len = dlc2len[dlc];
0179 } else {
0180 dest->len = dlc;
0181 if (dlc > 8)
0182 dest->len = 8;
0183 }
0184
0185 dp = (uint64_t *)&source->data0;
0186 for (j = 0; j < ((dest->len + 7) / 8); j++) {
0187 dest->data.dwords[j] = READ_DMA_DOUBLE(dp);
0188 if (++dp >= (uint64_t *)rxmax)
0189 dp = (uint64_t *)addr;
0190 }
0191
0192
0193 bds = grcan_numbds(dest->len);
0194 source += bds;
0195 if (source >= rxmax) {
0196 source = (struct grcanfd_bd0 *)
0197 ((void *)source - size);
0198 }
0199 dest++;
0200 ret++;
0201 bds_tot += bds;
0202 }
0203
0204
0205 SPIN_LOCK_IRQ(&pDev->devlock, oldLevel);
0206 if (pDev->started == STATE_STARTED) {
0207 regs->rx0rd = (unsigned int) source - addr;
0208 regs->rx0ctrl = GRCAN_RXCTRL_ENABLE;
0209 } else {
0210 DBGC(DBG_STATE, "cancelled due to a BUS OFF error\n");
0211 ret = state2err[pDev->started];
0212 }
0213 SPIN_UNLOCK_IRQ(&pDev->devlock, oldLevel);
0214
0215 return ret;
0216 }
0217 return 0;
0218 }
0219
0220 int grcanfd_read(void *d, CANFDMsg *msg, size_t ucount)
0221 {
0222 struct grcan_priv *pDev = d;
0223 CANFDMsg *dest;
0224 unsigned int count, left;
0225 int nread;
0226 int req_cnt;
0227
0228 FUNCDBG();
0229
0230 dest = msg;
0231 req_cnt = ucount;
0232
0233 if ( (!dest) || (req_cnt<1) )
0234 return GRCAN_RET_INVARG;
0235
0236 if (pDev->started != STATE_STARTED) {
0237 return GRCAN_RET_NOTSTARTED;
0238 }
0239
0240 DBGC(DBG_RX, "grcan_read [%p]: buf: %p len: %u\n", d, msg, (unsigned int) ucount);
0241
0242 nread = grcan_hw_read_try_fd(pDev,pDev->regs,dest,req_cnt);
0243 if (nread < 0) {
0244 return nread;
0245 }
0246 count = nread;
0247 if ( !( pDev->rxblock && pDev->rxcomplete && (count!=req_cnt) ) ){
0248 if ( count > 0 ) {
0249
0250 return count;
0251 }
0252
0253
0254 if ( !pDev->rxblock ) {
0255
0256 return GRCAN_RET_TIMEOUT;
0257 }
0258 }
0259
0260 while (count == 0 || (pDev->rxcomplete && (count!=req_cnt))) {
0261 if (!pDev->rxcomplete) {
0262 left = 1;
0263 } else {
0264 left = req_cnt - count;
0265
0266
0267
0268
0269
0270
0271 if (left > ((pDev->rxbuf_size/GRCAN_MSG_SIZE) / 2)){
0272 left = (pDev->rxbuf_size/GRCAN_MSG_SIZE) / 2;
0273 }
0274 }
0275
0276 nread = grcan_wait_rxdata(pDev, left);
0277 if (nread) {
0278
0279
0280
0281
0282 return nread;
0283 }
0284
0285
0286 nread = grcan_hw_read_try_fd(
0287 pDev,
0288 pDev->regs,
0289 dest+count,
0290 req_cnt-count);
0291
0292 if (nread < 0) {
0293
0294 return nread;
0295 }
0296 count += nread;
0297 }
0298
0299 return count;
0300 }
0301
0302 static int grcan_hw_write_try_fd(
0303 struct grcan_priv *pDev,
0304 struct grcan_regs *regs,
0305 CANFDMsg *buffer,
0306 int count)
0307 {
0308 unsigned int rp, wp, size, addr;
0309 int ret;
0310 struct grcanfd_bd0 *dest, *txmax;
0311 CANFDMsg *source = (CANFDMsg *) buffer;
0312 int space_left;
0313 unsigned int tmp;
0314 int i, bds;
0315 uint64_t *dp;
0316 uint8_t dlc;
0317 SPIN_IRQFLAGS(oldLevel);
0318
0319 DBGC(DBG_TX, "\n");
0320
0321 rp = READ_REG(®s->tx0rd);
0322 wp = READ_REG(®s->tx0wr);
0323 size = READ_REG(®s->tx0size);
0324 space_left = grcan_hw_txspace(rp, wp, size);
0325
0326 addr = (unsigned int)pDev->tx;
0327 dest = (struct grcanfd_bd0 *)(addr + wp);
0328 txmax = (struct grcanfd_bd0 *)(addr + size);
0329 ret = 0;
0330
0331 while (source < &buffer[count]) {
0332
0333 if (source->fdopts & GRCAN_FDOPT_FDFRM)
0334 bds = grcan_numbds(source->len);
0335 else
0336 bds = 1;
0337 if (space_left < bds)
0338 break;
0339
0340
0341 dlc = grcan_len2dlc(source->len);
0342 if (dlc < 0) {
0343
0344
0345
0346 if (ret <= 0)
0347 return GRCAN_RET_INVARG;
0348 break;
0349 }
0350 dest->head[1] = (dlc << 28) |
0351 ((source->fdopts & GRCAN_FDMASK) << 25);
0352 dp = &dest->data0;
0353 for (i = 0; i < ((source->len + 7) / 8); i++) {
0354 *dp++ = source->data.dwords[i];
0355 if (dp >= (uint64_t *)txmax)
0356 dp = (uint64_t *)addr;
0357 }
0358 if (source->extended) {
0359 tmp = (1 << 31) | (source->id & 0x3fffffff);
0360 } else {
0361 tmp = (source->id & 0xfff) << 18;
0362 }
0363 if (source->rtr)
0364 tmp |= (1 << 30);
0365 dest->head[0] = tmp;
0366 source++;
0367 dest += bds;
0368 if (dest >= txmax)
0369 dest = (struct grcanfd_bd0 *)((void *)dest - size);
0370 space_left -= bds;
0371 ret++;
0372 }
0373
0374
0375 SPIN_LOCK_IRQ(&pDev->devlock, oldLevel);
0376 if (pDev->started == STATE_STARTED) {
0377 regs->tx0wr = (unsigned int) dest - addr;
0378 regs->tx0ctrl = GRCAN_TXCTRL_ENABLE;
0379 } else {
0380 DBGC(DBG_STATE, "cancelled due to a BUS OFF error\n");
0381 ret = state2err[pDev->started];
0382 }
0383 SPIN_UNLOCK_IRQ(&pDev->devlock, oldLevel);
0384
0385 return ret;
0386 }
0387
0388 int grcanfd_write(
0389 void *d,
0390 CANFDMsg *msg,
0391 size_t ucount)
0392 {
0393 struct grcan_priv *pDev = d;
0394 CANFDMsg *source, *curr;
0395 unsigned int count, left;
0396 int nwritten;
0397 int req_cnt;
0398
0399 DBGC(DBG_TX,"\n");
0400
0401 if ((pDev->started != STATE_STARTED) || pDev->config.silent || pDev->flushing)
0402 return GRCAN_RET_NOTSTARTED;
0403
0404 req_cnt = ucount;
0405 curr = source = (CANFDMsg *) msg;
0406
0407
0408 if (( req_cnt < 1) || (source == NULL) ){
0409 return GRCAN_RET_INVARG;
0410 }
0411
0412 nwritten = grcan_hw_write_try_fd(pDev,pDev->regs,source,req_cnt);
0413 if (nwritten < 0) {
0414 return nwritten;
0415 }
0416 count = nwritten;
0417 if ( !(pDev->txblock && pDev->txcomplete && (count!=req_cnt)) ) {
0418 if ( count > 0 ) {
0419
0420 return count;
0421 }
0422
0423
0424 if ( !pDev->txblock ) {
0425
0426 return GRCAN_RET_TIMEOUT;
0427 }
0428 }
0429
0430
0431 while((count == 0) || (pDev->txcomplete && (count!=req_cnt)) ){
0432
0433
0434
0435
0436
0437
0438
0439 curr = &source[count];
0440 if (curr->fdopts & GRCAN_FDOPT_FDFRM)
0441 left = grcan_numbds(curr->len);
0442 else
0443 left = 1;
0444
0445 if (pDev->txcomplete) {
0446
0447
0448
0449 left += req_cnt - count - 1;
0450 if (left > ((pDev->txbuf_size/GRCAN_MSG_SIZE)/2)) {
0451 left = (pDev->txbuf_size/GRCAN_MSG_SIZE)/2;
0452 }
0453
0454 }
0455
0456 nwritten = grcan_wait_txspace(pDev,left);
0457
0458 if ( nwritten ) {
0459
0460
0461
0462
0463
0464 return nwritten;
0465 }
0466
0467
0468 nwritten = grcan_hw_write_try_fd(
0469 pDev,
0470 pDev->regs,
0471 source+count,
0472 req_cnt-count);
0473
0474 if (nwritten < 0) {
0475
0476 return nwritten;
0477 }
0478 count += nwritten;
0479 }
0480
0481
0482 return count;
0483 }
0484
0485 int grcanfd_set_speed(void *d, unsigned int nom_hz, unsigned int fd_hz)
0486 {
0487 struct grcan_priv *pDev = d;
0488 struct grlib_canbtrs_timing nom, fd;
0489 int ret;
0490
0491 FUNCDBG();
0492
0493
0494 if ((pDev->started == STATE_STARTED) || !pDev->fd_capable)
0495 return -1;
0496
0497
0498 ret = grlib_canbtrs_calc_timing(
0499 nom_hz, pDev->corefreq_hz, GRCAN_SAMPLING_POINT,
0500 &grcanfd_nom_btrs_ranges, &nom);
0501 if ( ret )
0502 return -2;
0503 ret = grlib_canbtrs_calc_timing(
0504 fd_hz, pDev->corefreq_hz, GRCAN_SAMPLING_POINT,
0505 &grcanfd_fd_btrs_ranges, &fd);
0506 if ( ret )
0507 return -2;
0508
0509
0510 pDev->config.timing = *(struct grcan_timing *)&nom;
0511 pDev->config.timing_fd.scaler = fd.scaler;
0512 pDev->config.timing_fd.ps1 = fd.ps1;
0513 pDev->config.timing_fd.ps2 = fd.ps2;
0514 pDev->config.timing_fd.sjw = fd.rsj;
0515 pDev->config.timing_fd.resv_zero = 0;
0516 pDev->config_changed = 1;
0517
0518 return 0;
0519
0520 }
0521
0522 int grcanfd_set_btrs(
0523 void *d,
0524 const struct grcanfd_timing *nominal,
0525 const struct grcanfd_timing *fd)
0526 {
0527 struct grcan_priv *pDev = d;
0528
0529 FUNCDBG();
0530
0531
0532
0533
0534 if ((pDev->started == STATE_STARTED) || !pDev->fd_capable)
0535 return -1;
0536
0537 if (!nominal)
0538 return -2;
0539
0540 pDev->config.timing.scaler = nominal->scaler;
0541 pDev->config.timing.ps1 = nominal->ps1;
0542 pDev->config.timing.ps2 = nominal->ps2;
0543 pDev->config.timing.rsj = nominal->sjw;
0544 pDev->config.timing.bpr = 0;
0545 if (fd) {
0546 pDev->config.timing_fd = *fd;
0547 } else {
0548 memset(&pDev->config.timing_fd, 0,
0549 sizeof(struct grcanfd_timing));
0550 }
0551 pDev->config_changed = 1;
0552
0553 return 0;
0554 }