cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

bittiming.c (8701B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/* Copyright (C) 2005 Marc Kleine-Budde, Pengutronix
      3 * Copyright (C) 2006 Andrey Volkov, Varma Electronics
      4 * Copyright (C) 2008-2009 Wolfgang Grandegger <wg@grandegger.com>
      5 */
      6
      7#include <linux/units.h>
      8#include <linux/can/dev.h>
      9
     10#ifdef CONFIG_CAN_CALC_BITTIMING
     11#define CAN_CALC_MAX_ERROR 50 /* in one-tenth of a percent */
     12
     13/* Bit-timing calculation derived from:
     14 *
     15 * Code based on LinCAN sources and H8S2638 project
     16 * Copyright 2004-2006 Pavel Pisa - DCE FELK CVUT cz
     17 * Copyright 2005      Stanislav Marek
     18 * email: pisa@cmp.felk.cvut.cz
     19 *
     20 * Calculates proper bit-timing parameters for a specified bit-rate
     21 * and sample-point, which can then be used to set the bit-timing
     22 * registers of the CAN controller. You can find more information
     23 * in the header file linux/can/netlink.h.
     24 */
     25static int
     26can_update_sample_point(const struct can_bittiming_const *btc,
     27			const unsigned int sample_point_nominal, const unsigned int tseg,
     28			unsigned int *tseg1_ptr, unsigned int *tseg2_ptr,
     29			unsigned int *sample_point_error_ptr)
     30{
     31	unsigned int sample_point_error, best_sample_point_error = UINT_MAX;
     32	unsigned int sample_point, best_sample_point = 0;
     33	unsigned int tseg1, tseg2;
     34	int i;
     35
     36	for (i = 0; i <= 1; i++) {
     37		tseg2 = tseg + CAN_SYNC_SEG -
     38			(sample_point_nominal * (tseg + CAN_SYNC_SEG)) /
     39			1000 - i;
     40		tseg2 = clamp(tseg2, btc->tseg2_min, btc->tseg2_max);
     41		tseg1 = tseg - tseg2;
     42		if (tseg1 > btc->tseg1_max) {
     43			tseg1 = btc->tseg1_max;
     44			tseg2 = tseg - tseg1;
     45		}
     46
     47		sample_point = 1000 * (tseg + CAN_SYNC_SEG - tseg2) /
     48			(tseg + CAN_SYNC_SEG);
     49		sample_point_error = abs(sample_point_nominal - sample_point);
     50
     51		if (sample_point <= sample_point_nominal &&
     52		    sample_point_error < best_sample_point_error) {
     53			best_sample_point = sample_point;
     54			best_sample_point_error = sample_point_error;
     55			*tseg1_ptr = tseg1;
     56			*tseg2_ptr = tseg2;
     57		}
     58	}
     59
     60	if (sample_point_error_ptr)
     61		*sample_point_error_ptr = best_sample_point_error;
     62
     63	return best_sample_point;
     64}
     65
     66int can_calc_bittiming(const struct net_device *dev, struct can_bittiming *bt,
     67		       const struct can_bittiming_const *btc)
     68{
     69	struct can_priv *priv = netdev_priv(dev);
     70	unsigned int bitrate;			/* current bitrate */
     71	unsigned int bitrate_error;		/* difference between current and nominal value */
     72	unsigned int best_bitrate_error = UINT_MAX;
     73	unsigned int sample_point_error;	/* difference between current and nominal value */
     74	unsigned int best_sample_point_error = UINT_MAX;
     75	unsigned int sample_point_nominal;	/* nominal sample point */
     76	unsigned int best_tseg = 0;		/* current best value for tseg */
     77	unsigned int best_brp = 0;		/* current best value for brp */
     78	unsigned int brp, tsegall, tseg, tseg1 = 0, tseg2 = 0;
     79	u64 v64;
     80
     81	/* Use CiA recommended sample points */
     82	if (bt->sample_point) {
     83		sample_point_nominal = bt->sample_point;
     84	} else {
     85		if (bt->bitrate > 800 * KILO /* BPS */)
     86			sample_point_nominal = 750;
     87		else if (bt->bitrate > 500 * KILO /* BPS */)
     88			sample_point_nominal = 800;
     89		else
     90			sample_point_nominal = 875;
     91	}
     92
     93	/* tseg even = round down, odd = round up */
     94	for (tseg = (btc->tseg1_max + btc->tseg2_max) * 2 + 1;
     95	     tseg >= (btc->tseg1_min + btc->tseg2_min) * 2; tseg--) {
     96		tsegall = CAN_SYNC_SEG + tseg / 2;
     97
     98		/* Compute all possible tseg choices (tseg=tseg1+tseg2) */
     99		brp = priv->clock.freq / (tsegall * bt->bitrate) + tseg % 2;
    100
    101		/* choose brp step which is possible in system */
    102		brp = (brp / btc->brp_inc) * btc->brp_inc;
    103		if (brp < btc->brp_min || brp > btc->brp_max)
    104			continue;
    105
    106		bitrate = priv->clock.freq / (brp * tsegall);
    107		bitrate_error = abs(bt->bitrate - bitrate);
    108
    109		/* tseg brp biterror */
    110		if (bitrate_error > best_bitrate_error)
    111			continue;
    112
    113		/* reset sample point error if we have a better bitrate */
    114		if (bitrate_error < best_bitrate_error)
    115			best_sample_point_error = UINT_MAX;
    116
    117		can_update_sample_point(btc, sample_point_nominal, tseg / 2,
    118					&tseg1, &tseg2, &sample_point_error);
    119		if (sample_point_error >= best_sample_point_error)
    120			continue;
    121
    122		best_sample_point_error = sample_point_error;
    123		best_bitrate_error = bitrate_error;
    124		best_tseg = tseg / 2;
    125		best_brp = brp;
    126
    127		if (bitrate_error == 0 && sample_point_error == 0)
    128			break;
    129	}
    130
    131	if (best_bitrate_error) {
    132		/* Error in one-tenth of a percent */
    133		v64 = (u64)best_bitrate_error * 1000;
    134		do_div(v64, bt->bitrate);
    135		bitrate_error = (u32)v64;
    136		if (bitrate_error > CAN_CALC_MAX_ERROR) {
    137			netdev_err(dev,
    138				   "bitrate error %d.%d%% too high\n",
    139				   bitrate_error / 10, bitrate_error % 10);
    140			return -EDOM;
    141		}
    142		netdev_warn(dev, "bitrate error %d.%d%%\n",
    143			    bitrate_error / 10, bitrate_error % 10);
    144	}
    145
    146	/* real sample point */
    147	bt->sample_point = can_update_sample_point(btc, sample_point_nominal,
    148						   best_tseg, &tseg1, &tseg2,
    149						   NULL);
    150
    151	v64 = (u64)best_brp * 1000 * 1000 * 1000;
    152	do_div(v64, priv->clock.freq);
    153	bt->tq = (u32)v64;
    154	bt->prop_seg = tseg1 / 2;
    155	bt->phase_seg1 = tseg1 - bt->prop_seg;
    156	bt->phase_seg2 = tseg2;
    157
    158	/* check for sjw user settings */
    159	if (!bt->sjw || !btc->sjw_max) {
    160		bt->sjw = 1;
    161	} else {
    162		/* bt->sjw is at least 1 -> sanitize upper bound to sjw_max */
    163		if (bt->sjw > btc->sjw_max)
    164			bt->sjw = btc->sjw_max;
    165		/* bt->sjw must not be higher than tseg2 */
    166		if (tseg2 < bt->sjw)
    167			bt->sjw = tseg2;
    168	}
    169
    170	bt->brp = best_brp;
    171
    172	/* real bitrate */
    173	bt->bitrate = priv->clock.freq /
    174		(bt->brp * (CAN_SYNC_SEG + tseg1 + tseg2));
    175
    176	return 0;
    177}
    178
    179void can_calc_tdco(struct can_tdc *tdc, const struct can_tdc_const *tdc_const,
    180		   const struct can_bittiming *dbt,
    181		   u32 *ctrlmode, u32 ctrlmode_supported)
    182
    183{
    184	if (!tdc_const || !(ctrlmode_supported & CAN_CTRLMODE_TDC_AUTO))
    185		return;
    186
    187	*ctrlmode &= ~CAN_CTRLMODE_TDC_MASK;
    188
    189	/* As specified in ISO 11898-1 section 11.3.3 "Transmitter
    190	 * delay compensation" (TDC) is only applicable if data BRP is
    191	 * one or two.
    192	 */
    193	if (dbt->brp == 1 || dbt->brp == 2) {
    194		/* Sample point in clock periods */
    195		u32 sample_point_in_tc = (CAN_SYNC_SEG + dbt->prop_seg +
    196					  dbt->phase_seg1) * dbt->brp;
    197
    198		if (sample_point_in_tc < tdc_const->tdco_min)
    199			return;
    200		tdc->tdco = min(sample_point_in_tc, tdc_const->tdco_max);
    201		*ctrlmode |= CAN_CTRLMODE_TDC_AUTO;
    202	}
    203}
    204#endif /* CONFIG_CAN_CALC_BITTIMING */
    205
    206/* Checks the validity of the specified bit-timing parameters prop_seg,
    207 * phase_seg1, phase_seg2 and sjw and tries to determine the bitrate
    208 * prescaler value brp. You can find more information in the header
    209 * file linux/can/netlink.h.
    210 */
    211static int can_fixup_bittiming(const struct net_device *dev, struct can_bittiming *bt,
    212			       const struct can_bittiming_const *btc)
    213{
    214	const struct can_priv *priv = netdev_priv(dev);
    215	unsigned int tseg1, alltseg;
    216	u64 brp64;
    217
    218	tseg1 = bt->prop_seg + bt->phase_seg1;
    219	if (!bt->sjw)
    220		bt->sjw = 1;
    221	if (bt->sjw > btc->sjw_max ||
    222	    tseg1 < btc->tseg1_min || tseg1 > btc->tseg1_max ||
    223	    bt->phase_seg2 < btc->tseg2_min || bt->phase_seg2 > btc->tseg2_max)
    224		return -ERANGE;
    225
    226	brp64 = (u64)priv->clock.freq * (u64)bt->tq;
    227	if (btc->brp_inc > 1)
    228		do_div(brp64, btc->brp_inc);
    229	brp64 += 500000000UL - 1;
    230	do_div(brp64, 1000000000UL); /* the practicable BRP */
    231	if (btc->brp_inc > 1)
    232		brp64 *= btc->brp_inc;
    233	bt->brp = (u32)brp64;
    234
    235	if (bt->brp < btc->brp_min || bt->brp > btc->brp_max)
    236		return -EINVAL;
    237
    238	alltseg = bt->prop_seg + bt->phase_seg1 + bt->phase_seg2 + 1;
    239	bt->bitrate = priv->clock.freq / (bt->brp * alltseg);
    240	bt->sample_point = ((tseg1 + 1) * 1000) / alltseg;
    241
    242	return 0;
    243}
    244
    245/* Checks the validity of predefined bitrate settings */
    246static int
    247can_validate_bitrate(const struct net_device *dev, const struct can_bittiming *bt,
    248		     const u32 *bitrate_const,
    249		     const unsigned int bitrate_const_cnt)
    250{
    251	unsigned int i;
    252
    253	for (i = 0; i < bitrate_const_cnt; i++) {
    254		if (bt->bitrate == bitrate_const[i])
    255			return 0;
    256	}
    257
    258	return -EINVAL;
    259}
    260
    261int can_get_bittiming(const struct net_device *dev, struct can_bittiming *bt,
    262		      const struct can_bittiming_const *btc,
    263		      const u32 *bitrate_const,
    264		      const unsigned int bitrate_const_cnt)
    265{
    266	int err;
    267
    268	/* Depending on the given can_bittiming parameter structure the CAN
    269	 * timing parameters are calculated based on the provided bitrate OR
    270	 * alternatively the CAN timing parameters (tq, prop_seg, etc.) are
    271	 * provided directly which are then checked and fixed up.
    272	 */
    273	if (!bt->tq && bt->bitrate && btc)
    274		err = can_calc_bittiming(dev, bt, btc);
    275	else if (bt->tq && !bt->bitrate && btc)
    276		err = can_fixup_bittiming(dev, bt, btc);
    277	else if (!bt->tq && bt->bitrate && bitrate_const)
    278		err = can_validate_bitrate(dev, bt, bitrate_const,
    279					   bitrate_const_cnt);
    280	else
    281		err = -EINVAL;
    282
    283	return err;
    284}