From 7db032cf0216747a87b2ad4b0af07f073cb8a722 Mon Sep 17 00:00:00 2001 From: Daniel Hellstrom Date: Fri, 12 Apr 2019 12:54:54 +0200 Subject: leon,occan: use common CAN baud-rate calculation routine Update #4306. --- bsps/shared/grlib/can/occan.c | 151 ++++++++++++------------------------------ 1 file changed, 41 insertions(+), 110 deletions(-) diff --git a/bsps/shared/grlib/can/occan.c b/bsps/shared/grlib/can/occan.c index 59b4f234f6..01537f9390 100644 --- a/bsps/shared/grlib/can/occan.c +++ b/bsps/shared/grlib/can/occan.c @@ -19,6 +19,7 @@ #include #include #include +#include #include @@ -185,19 +186,20 @@ typedef struct { #define pelican_regs pelican32_regs #endif +/* Default sampling point in % */ +#define OCCAN_SAMPLING_POINT 90 + +/* OCCAN baud-rate paramter boundaries */ +struct grlib_canbtrs_ranges occan_btrs_ranges = { + .max_scaler = 64, + .has_bpr = 0, + .divfactor = 1, + .min_tseg1 = 1, + .max_tseg1 = 16, + .min_tseg2 = 1, + .max_tseg2 = 8, +}; -#define MAX_TSEG2 7 -#define MAX_TSEG1 15 - -#if 0 -typedef struct { - unsigned char brp; - unsigned char sjw; - unsigned char tseg1; - unsigned char tseg2; - unsigned char sam; -} occan_speed_regs; -#endif typedef struct { unsigned char btr0; unsigned char btr1; @@ -251,7 +253,9 @@ static CANMsg *occan_fifo_claim_get(occan_fifo *fifo); static void occan_fifo_clr(occan_fifo *fifo); /**** Hardware related Interface ****/ -static int occan_calc_speedregs(unsigned int clock_hz, unsigned int rate, occan_speed_regs *result); +static void convert_timing_to_btrs( + struct grlib_canbtrs_timing *t, + occan_speed_regs *btrs); static int occan_set_speedregs(occan_priv *priv, occan_speed_regs *timing); static void pelican_init(occan_priv *priv); static void pelican_open(occan_priv *priv); @@ -765,6 +769,7 @@ static void pelican_init(occan_priv *priv){ static void pelican_open(occan_priv *priv){ int ret; + struct grlib_canbtrs_timing timing; /* Set defaults */ priv->speed = OCCAN_SPEED_250K; @@ -783,13 +788,19 @@ static void pelican_open(occan_priv *priv){ */ WRITE_REG(priv, &priv->regs->clkdiv, (1<sys_freq_hz,priv->speed,&priv->timing); - if ( ret ){ + ret = grlib_canbtrs_calc_timing( + priv->speed, priv->sys_freq_hz, + OCCAN_SAMPLING_POINT, &occan_btrs_ranges, + (struct grlib_canbtrs_timing *)&timing); + if ( ret ) { /* failed to set speed for this system freq, try with 50K instead */ priv->speed = OCCAN_SPEED_50K; - occan_calc_speedregs(priv->sys_freq_hz, priv->speed, - &priv->timing); + grlib_canbtrs_calc_timing( + priv->speed, priv->sys_freq_hz, + OCCAN_SAMPLING_POINT, &occan_btrs_ranges, + (struct grlib_canbtrs_timing *)&timing); } + convert_timing_to_btrs(&timing, &priv->timing); /* disable all interrupts */ WRITE_REG(priv, &priv->regs->inten, 0); @@ -983,97 +994,13 @@ static void pelican_set_accept(occan_priv *priv, unsigned char *acode, unsigned WRITE_REG(priv, amask3, amask[3]); } - -/* This function calculates BTR0 and BTR1 values for a given bitrate. - * - * Set communication parameters. - * \param clock_hz OC_CAN Core frequency in Hz. - * \param rate Requested baud rate in bits/second. - * \param result Pointer to where resulting BTRs will be stored. - * \return zero if successful to calculate a baud rate. - */ -static int occan_calc_speedregs(unsigned int clock_hz, unsigned int rate, occan_speed_regs *result) +static void convert_timing_to_btrs( + struct grlib_canbtrs_timing *t, + occan_speed_regs *btrs) { - int best_error = 1000000000; - int error; - int best_tseg=0, best_brp=0, brp=0; - int tseg=0, tseg1=0, tseg2=0; - int sjw = 0; - int clock = clock_hz / 2; - int sampl_pt = 90; - - if ( (rate<5000) || (rate>1000000) ){ - /* invalid speed mode */ - return -1; - } - - /* find best match, return -2 if no good reg - * combination is available for this frequency */ - - /* some heuristic specials */ - if (rate > ((1000000 + 500000) / 2)) - sampl_pt = 75; - - if (rate < ((12500 + 10000) / 2)) - sampl_pt = 75; - - if (rate < ((100000 + 125000) / 2)) - sjw = 1; - - /* tseg even = round down, odd = round up */ - for (tseg = (0 + 0 + 2) * 2; - tseg <= (MAX_TSEG2 + MAX_TSEG1 + 2) * 2 + 1; - tseg++) - { - brp = clock / ((1 + tseg / 2) * rate) + tseg % 2; - if ((brp == 0) || (brp > 64)) - continue; - - error = rate - clock / (brp * (1 + tseg / 2)); - if (error < 0) - { - error = -error; - } - - if (error <= best_error) - { - best_error = error; - best_tseg = tseg/2; - best_brp = brp-1; - } - } - - if (best_error && (rate / best_error < 10)) - { - printk("OCCAN: bitrate %d is not possible with %d Hz clock\n\r",rate, clock); - return -2; - }else if ( !result ) - return 0; /* nothing to store result in, but a valid bitrate can be calculated */ - - tseg2 = best_tseg - (sampl_pt * (best_tseg + 1)) / 100; - - if (tseg2 < 0) - { - tseg2 = 0; - } - - if (tseg2 > MAX_TSEG2) - { - tseg2 = MAX_TSEG2; - } - - tseg1 = best_tseg - tseg2 - 2; - - if (tseg1 > MAX_TSEG1) - { - tseg1 = MAX_TSEG1; - tseg2 = best_tseg - tseg1 - 2; - } - - result->btr0 = (sjw<btr1 = (0<<7) | (tseg2<btr0 = (t->rsj << OCCAN_BUSTIM_SJW_BIT) | + (t->scaler & OCCAN_BUSTIM_BRP); + btrs->btr1 = (0<<7) | (t->ps2 << OCCAN_BUSTIM_TSEG2_BIT) | t->ps1; } static int occan_set_speedregs(occan_priv *priv, occan_speed_regs *timing) @@ -1441,7 +1368,7 @@ static rtems_device_driver occan_write(rtems_device_major_number major, rtems_de static rtems_device_driver occan_ioctl(rtems_device_major_number major, rtems_device_minor_number minor, void *arg) { int ret; - occan_speed_regs timing; + struct grlib_canbtrs_timing timing; occan_priv *can; struct drvmgr_dev *dev; unsigned int speed; @@ -1467,7 +1394,11 @@ static rtems_device_driver occan_ioctl(rtems_device_major_number major, rtems_de /* get speed rate from argument */ speed = (unsigned int)ioarg->buffer; - ret = occan_calc_speedregs(can->sys_freq_hz,speed,&timing); + /* Calculate default timing register values */ + ret = grlib_canbtrs_calc_timing( + speed, can->sys_freq_hz, + OCCAN_SAMPLING_POINT, &occan_btrs_ranges, + (struct grlib_canbtrs_timing *)&timing); if ( ret ) return RTEMS_INVALID_NAME; /* EINVAL */ @@ -1476,7 +1407,7 @@ static rtems_device_driver occan_ioctl(rtems_device_major_number major, rtems_de /* save timing/speed */ can->speed = speed; - can->timing = timing; + convert_timing_to_btrs(&timing, &can->timing); break; case OCCAN_IOC_SET_BTRS: -- cgit v1.2.3