can: bittiming: can_fixup_bittiming(): report error via netlink and harmonize error...
[platform/kernel/linux-starfive.git] / drivers / net / can / dev / bittiming.c
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 1 as default */
15         bt->sjw = 1;
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                 return -ERANGE;
23
24         return 0;
25 }
26
27 /* Checks the validity of the specified bit-timing parameters prop_seg,
28  * phase_seg1, phase_seg2 and sjw and tries to determine the bitrate
29  * prescaler value brp. You can find more information in the header
30  * file linux/can/netlink.h.
31  */
32 static int can_fixup_bittiming(const struct net_device *dev, struct can_bittiming *bt,
33                                const struct can_bittiming_const *btc,
34                                struct netlink_ext_ack *extack)
35 {
36         const unsigned int tseg1 = bt->prop_seg + bt->phase_seg1;
37         const struct can_priv *priv = netdev_priv(dev);
38         u64 brp64;
39         int err;
40
41         if (tseg1 < btc->tseg1_min) {
42                 NL_SET_ERR_MSG_FMT(extack, "prop-seg + phase-seg1: %u less than tseg1-min: %u",
43                                    tseg1, btc->tseg1_min);
44                 return -EINVAL;
45         }
46         if (tseg1 > btc->tseg1_max) {
47                 NL_SET_ERR_MSG_FMT(extack, "prop-seg + phase-seg1: %u greater than tseg1-max: %u",
48                                    tseg1, btc->tseg1_max);
49                 return -EINVAL;
50         }
51         if (bt->phase_seg2 < btc->tseg2_min) {
52                 NL_SET_ERR_MSG_FMT(extack, "phase-seg2: %u less than tseg2-min: %u",
53                                    bt->phase_seg2, btc->tseg2_min);
54                 return -EINVAL;
55         }
56         if (bt->phase_seg2 > btc->tseg2_max) {
57                 NL_SET_ERR_MSG_FMT(extack, "phase-seg2: %u greater than tseg2-max: %u",
58                                    bt->phase_seg2, btc->tseg2_max);
59                 return -EINVAL;
60         }
61
62         can_sjw_set_default(bt);
63
64         err = can_sjw_check(dev, bt, btc, extack);
65         if (err)
66                 return err;
67
68         brp64 = (u64)priv->clock.freq * (u64)bt->tq;
69         if (btc->brp_inc > 1)
70                 do_div(brp64, btc->brp_inc);
71         brp64 += 500000000UL - 1;
72         do_div(brp64, 1000000000UL); /* the practicable BRP */
73         if (btc->brp_inc > 1)
74                 brp64 *= btc->brp_inc;
75         bt->brp = (u32)brp64;
76
77         if (bt->brp < btc->brp_min) {
78                 NL_SET_ERR_MSG_FMT(extack, "resulting brp: %u less than brp-min: %u",
79                                    bt->brp, btc->brp_min);
80                 return -EINVAL;
81         }
82         if (bt->brp > btc->brp_max) {
83                 NL_SET_ERR_MSG_FMT(extack, "resulting brp: %u greater than brp-max: %u",
84                                    bt->brp, btc->brp_max);
85                 return -EINVAL;
86         }
87
88         bt->bitrate = priv->clock.freq / (bt->brp * can_bit_time(bt));
89         bt->sample_point = ((CAN_SYNC_SEG + tseg1) * 1000) / can_bit_time(bt);
90         bt->tq = DIV_U64_ROUND_CLOSEST(mul_u32_u32(bt->brp, NSEC_PER_SEC),
91                                        priv->clock.freq);
92
93         return 0;
94 }
95
96 /* Checks the validity of predefined bitrate settings */
97 static int
98 can_validate_bitrate(const struct net_device *dev, const struct can_bittiming *bt,
99                      const u32 *bitrate_const,
100                      const unsigned int bitrate_const_cnt,
101                      struct netlink_ext_ack *extack)
102 {
103         unsigned int i;
104
105         for (i = 0; i < bitrate_const_cnt; i++) {
106                 if (bt->bitrate == bitrate_const[i])
107                         return 0;
108         }
109
110         return -EINVAL;
111 }
112
113 int can_get_bittiming(const struct net_device *dev, struct can_bittiming *bt,
114                       const struct can_bittiming_const *btc,
115                       const u32 *bitrate_const,
116                       const unsigned int bitrate_const_cnt,
117                       struct netlink_ext_ack *extack)
118 {
119         /* Depending on the given can_bittiming parameter structure the CAN
120          * timing parameters are calculated based on the provided bitrate OR
121          * alternatively the CAN timing parameters (tq, prop_seg, etc.) are
122          * provided directly which are then checked and fixed up.
123          */
124         if (!bt->tq && bt->bitrate && btc)
125                 return can_calc_bittiming(dev, bt, btc, extack);
126         if (bt->tq && !bt->bitrate && btc)
127                 return can_fixup_bittiming(dev, bt, btc, extack);
128         if (!bt->tq && bt->bitrate && bitrate_const)
129                 return can_validate_bitrate(dev, bt, bitrate_const,
130                                             bitrate_const_cnt, extack);
131
132         return -EINVAL;
133 }