xref: /openbmc/linux/drivers/net/can/dev/bittiming.c (revision 7ae5c03a)
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/can/dev.h>
8 
9 /* Checks the validity of the specified bit-timing parameters prop_seg,
10  * phase_seg1, phase_seg2 and sjw and tries to determine the bitrate
11  * prescaler value brp. You can find more information in the header
12  * file linux/can/netlink.h.
13  */
14 static int can_fixup_bittiming(const struct net_device *dev, struct can_bittiming *bt,
15 			       const struct can_bittiming_const *btc)
16 {
17 	const struct can_priv *priv = netdev_priv(dev);
18 	unsigned int tseg1, alltseg;
19 	u64 brp64;
20 
21 	tseg1 = bt->prop_seg + bt->phase_seg1;
22 	if (!bt->sjw)
23 		bt->sjw = 1;
24 	if (bt->sjw > btc->sjw_max ||
25 	    tseg1 < btc->tseg1_min || tseg1 > btc->tseg1_max ||
26 	    bt->phase_seg2 < btc->tseg2_min || bt->phase_seg2 > btc->tseg2_max)
27 		return -ERANGE;
28 
29 	brp64 = (u64)priv->clock.freq * (u64)bt->tq;
30 	if (btc->brp_inc > 1)
31 		do_div(brp64, btc->brp_inc);
32 	brp64 += 500000000UL - 1;
33 	do_div(brp64, 1000000000UL); /* the practicable BRP */
34 	if (btc->brp_inc > 1)
35 		brp64 *= btc->brp_inc;
36 	bt->brp = (u32)brp64;
37 
38 	if (bt->brp < btc->brp_min || bt->brp > btc->brp_max)
39 		return -EINVAL;
40 
41 	alltseg = bt->prop_seg + bt->phase_seg1 + bt->phase_seg2 + 1;
42 	bt->bitrate = priv->clock.freq / (bt->brp * alltseg);
43 	bt->sample_point = ((tseg1 + 1) * 1000) / alltseg;
44 
45 	return 0;
46 }
47 
48 /* Checks the validity of predefined bitrate settings */
49 static int
50 can_validate_bitrate(const struct net_device *dev, const struct can_bittiming *bt,
51 		     const u32 *bitrate_const,
52 		     const unsigned int bitrate_const_cnt)
53 {
54 	unsigned int i;
55 
56 	for (i = 0; i < bitrate_const_cnt; i++) {
57 		if (bt->bitrate == bitrate_const[i])
58 			return 0;
59 	}
60 
61 	return -EINVAL;
62 }
63 
64 int can_get_bittiming(const struct net_device *dev, struct can_bittiming *bt,
65 		      const struct can_bittiming_const *btc,
66 		      const u32 *bitrate_const,
67 		      const unsigned int bitrate_const_cnt)
68 {
69 	int err;
70 
71 	/* Depending on the given can_bittiming parameter structure the CAN
72 	 * timing parameters are calculated based on the provided bitrate OR
73 	 * alternatively the CAN timing parameters (tq, prop_seg, etc.) are
74 	 * provided directly which are then checked and fixed up.
75 	 */
76 	if (!bt->tq && bt->bitrate && btc)
77 		err = can_calc_bittiming(dev, bt, btc);
78 	else if (bt->tq && !bt->bitrate && btc)
79 		err = can_fixup_bittiming(dev, bt, btc);
80 	else if (!bt->tq && bt->bitrate && bitrate_const)
81 		err = can_validate_bitrate(dev, bt, bitrate_const,
82 					   bitrate_const_cnt);
83 	else
84 		err = -EINVAL;
85 
86 	return err;
87 }
88