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 | void 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 | |
18 | int 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 bitrate |
46 | * prescaler value brp. You can find more information in the header |
47 | * file linux/can/netlink.h. |
48 | */ |
49 | static 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 */ |
114 | static int |
115 | can_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 | |
133 | int 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 CAN |
140 | * timing parameters are calculated based on the provided bitrate OR |
141 | * alternatively the CAN timing parameters (tq, prop_seg, etc.) are |
142 | * 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 | |