brintos

brintos / linux-shallow public Read only

0
0
Text · 4.5 KiB · 0b93900 Raw
154 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/* Copyright (C) 2005 Marc Kleine-Budde, Pengutronix3 * Copyright (C) 2006 Andrey Volkov, Varma Electronics4 * Copyright (C) 2008-2009 Wolfgang Grandegger <wg@grandegger.com>5 */6 7#include <linux/can/dev.h>8 9void can_sjw_set_default(struct can_bittiming *bt)10{11	if (bt->sjw)12		return;13 14	/* If user space provides no sjw, use sane default of phase_seg2 / 2 */15	bt->sjw = max(1U, min(bt->phase_seg1, bt->phase_seg2 / 2));16}17 18int can_sjw_check(const struct net_device *dev, const struct can_bittiming *bt,19		  const struct can_bittiming_const *btc, struct netlink_ext_ack *extack)20{21	if (bt->sjw > btc->sjw_max) {22		NL_SET_ERR_MSG_FMT(extack, "sjw: %u greater than max sjw: %u",23				   bt->sjw, btc->sjw_max);24		return -EINVAL;25	}26 27	if (bt->sjw > bt->phase_seg1) {28		NL_SET_ERR_MSG_FMT(extack,29				   "sjw: %u greater than phase-seg1: %u",30				   bt->sjw, bt->phase_seg1);31		return -EINVAL;32	}33 34	if (bt->sjw > bt->phase_seg2) {35		NL_SET_ERR_MSG_FMT(extack,36				   "sjw: %u greater than phase-seg2: %u",37				   bt->sjw, bt->phase_seg2);38		return -EINVAL;39	}40 41	return 0;42}43 44/* Checks the validity of the specified bit-timing parameters prop_seg,45 * phase_seg1, phase_seg2 and sjw and tries to determine the bitrate46 * prescaler value brp. You can find more information in the header47 * file linux/can/netlink.h.48 */49static int can_fixup_bittiming(const struct net_device *dev, struct can_bittiming *bt,50			       const struct can_bittiming_const *btc,51			       struct netlink_ext_ack *extack)52{53	const unsigned int tseg1 = bt->prop_seg + bt->phase_seg1;54	const struct can_priv *priv = netdev_priv(dev);55	u64 brp64;56	int err;57 58	if (tseg1 < btc->tseg1_min) {59		NL_SET_ERR_MSG_FMT(extack, "prop-seg + phase-seg1: %u less than tseg1-min: %u",60				   tseg1, btc->tseg1_min);61		return -EINVAL;62	}63	if (tseg1 > btc->tseg1_max) {64		NL_SET_ERR_MSG_FMT(extack, "prop-seg + phase-seg1: %u greater than tseg1-max: %u",65				   tseg1, btc->tseg1_max);66		return -EINVAL;67	}68	if (bt->phase_seg2 < btc->tseg2_min) {69		NL_SET_ERR_MSG_FMT(extack, "phase-seg2: %u less than tseg2-min: %u",70				   bt->phase_seg2, btc->tseg2_min);71		return -EINVAL;72	}73	if (bt->phase_seg2 > btc->tseg2_max) {74		NL_SET_ERR_MSG_FMT(extack, "phase-seg2: %u greater than tseg2-max: %u",75				   bt->phase_seg2, btc->tseg2_max);76		return -EINVAL;77	}78 79	can_sjw_set_default(bt);80 81	err = can_sjw_check(dev, bt, btc, extack);82	if (err)83		return err;84 85	brp64 = (u64)priv->clock.freq * (u64)bt->tq;86	if (btc->brp_inc > 1)87		do_div(brp64, btc->brp_inc);88	brp64 += 500000000UL - 1;89	do_div(brp64, 1000000000UL); /* the practicable BRP */90	if (btc->brp_inc > 1)91		brp64 *= btc->brp_inc;92	bt->brp = (u32)brp64;93 94	if (bt->brp < btc->brp_min) {95		NL_SET_ERR_MSG_FMT(extack, "resulting brp: %u less than brp-min: %u",96				   bt->brp, btc->brp_min);97		return -EINVAL;98	}99	if (bt->brp > btc->brp_max) {100		NL_SET_ERR_MSG_FMT(extack, "resulting brp: %u greater than brp-max: %u",101				   bt->brp, btc->brp_max);102		return -EINVAL;103	}104 105	bt->bitrate = priv->clock.freq / (bt->brp * can_bit_time(bt));106	bt->sample_point = ((CAN_SYNC_SEG + tseg1) * 1000) / can_bit_time(bt);107	bt->tq = DIV_U64_ROUND_CLOSEST(mul_u32_u32(bt->brp, NSEC_PER_SEC),108				       priv->clock.freq);109 110	return 0;111}112 113/* Checks the validity of predefined bitrate settings */114static int115can_validate_bitrate(const struct net_device *dev, const struct can_bittiming *bt,116		     const u32 *bitrate_const,117		     const unsigned int bitrate_const_cnt,118		     struct netlink_ext_ack *extack)119{120	unsigned int i;121 122	for (i = 0; i < bitrate_const_cnt; i++) {123		if (bt->bitrate == bitrate_const[i])124			return 0;125	}126 127	NL_SET_ERR_MSG_FMT(extack, "bitrate %u bps not supported",128			   bt->brp);129 130	return -EINVAL;131}132 133int can_get_bittiming(const struct net_device *dev, struct can_bittiming *bt,134		      const struct can_bittiming_const *btc,135		      const u32 *bitrate_const,136		      const unsigned int bitrate_const_cnt,137		      struct netlink_ext_ack *extack)138{139	/* Depending on the given can_bittiming parameter structure the CAN140	 * timing parameters are calculated based on the provided bitrate OR141	 * alternatively the CAN timing parameters (tq, prop_seg, etc.) are142	 * provided directly which are then checked and fixed up.143	 */144	if (!bt->tq && bt->bitrate && btc)145		return can_calc_bittiming(dev, bt, btc, extack);146	if (bt->tq && !bt->bitrate && btc)147		return can_fixup_bittiming(dev, bt, btc, extack);148	if (!bt->tq && bt->bitrate && bitrate_const)149		return can_validate_bitrate(dev, bt, bitrate_const,150					    bitrate_const_cnt, extack);151 152	return -EINVAL;153}154