0001
0002
0003
0004
0005
0006
0007 #include <linux/can/dev.h>
0008
0009
0010
0011
0012
0013
0014 static int can_fixup_bittiming(const struct net_device *dev, struct can_bittiming *bt,
0015 const struct can_bittiming_const *btc)
0016 {
0017 const struct can_priv *priv = netdev_priv(dev);
0018 unsigned int tseg1, alltseg;
0019 u64 brp64;
0020
0021 tseg1 = bt->prop_seg + bt->phase_seg1;
0022 if (!bt->sjw)
0023 bt->sjw = 1;
0024 if (bt->sjw > btc->sjw_max ||
0025 tseg1 < btc->tseg1_min || tseg1 > btc->tseg1_max ||
0026 bt->phase_seg2 < btc->tseg2_min || bt->phase_seg2 > btc->tseg2_max)
0027 return -ERANGE;
0028
0029 brp64 = (u64)priv->clock.freq * (u64)bt->tq;
0030 if (btc->brp_inc > 1)
0031 do_div(brp64, btc->brp_inc);
0032 brp64 += 500000000UL - 1;
0033 do_div(brp64, 1000000000UL);
0034 if (btc->brp_inc > 1)
0035 brp64 *= btc->brp_inc;
0036 bt->brp = (u32)brp64;
0037
0038 if (bt->brp < btc->brp_min || bt->brp > btc->brp_max)
0039 return -EINVAL;
0040
0041 alltseg = bt->prop_seg + bt->phase_seg1 + bt->phase_seg2 + 1;
0042 bt->bitrate = priv->clock.freq / (bt->brp * alltseg);
0043 bt->sample_point = ((tseg1 + 1) * 1000) / alltseg;
0044
0045 return 0;
0046 }
0047
0048
0049 static int
0050 can_validate_bitrate(const struct net_device *dev, const struct can_bittiming *bt,
0051 const u32 *bitrate_const,
0052 const unsigned int bitrate_const_cnt)
0053 {
0054 unsigned int i;
0055
0056 for (i = 0; i < bitrate_const_cnt; i++) {
0057 if (bt->bitrate == bitrate_const[i])
0058 return 0;
0059 }
0060
0061 return -EINVAL;
0062 }
0063
0064 int can_get_bittiming(const struct net_device *dev, struct can_bittiming *bt,
0065 const struct can_bittiming_const *btc,
0066 const u32 *bitrate_const,
0067 const unsigned int bitrate_const_cnt)
0068 {
0069 int err;
0070
0071
0072
0073
0074
0075
0076 if (!bt->tq && bt->bitrate && btc)
0077 err = can_calc_bittiming(dev, bt, btc);
0078 else if (bt->tq && !bt->bitrate && btc)
0079 err = can_fixup_bittiming(dev, bt, btc);
0080 else if (!bt->tq && bt->bitrate && bitrate_const)
0081 err = can_validate_bitrate(dev, bt, bitrate_const,
0082 bitrate_const_cnt);
0083 else
0084 err = -EINVAL;
0085
0086 return err;
0087 }