summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/net/can/dev/bittiming.c24
-rw-r--r--drivers/net/can/dev/netlink.c2
-rw-r--r--include/linux/can/bittiming.h6
3 files changed, 32 insertions, 0 deletions
diff --git a/drivers/net/can/dev/bittiming.c b/drivers/net/can/dev/bittiming.c
index f7fe226bb395..2907e60c9a57 100644
--- a/drivers/net/can/dev/bittiming.c
+++ b/drivers/net/can/dev/bittiming.c
@@ -174,6 +174,30 @@ int can_calc_bittiming(struct net_device *dev, struct can_bittiming *bt,
return 0;
}
+
+void can_calc_tdco(struct net_device *dev)
+{
+ struct can_priv *priv = netdev_priv(dev);
+ const struct can_bittiming *dbt = &priv->data_bittiming;
+ struct can_tdc *tdc = &priv->tdc;
+ const struct can_tdc_const *tdc_const = priv->tdc_const;
+
+ if (!tdc_const)
+ return;
+
+ /* As specified in ISO 11898-1 section 11.3.3 "Transmitter
+ * delay compensation" (TDC) is only applicable if data BRP is
+ * one or two.
+ */
+ if (dbt->brp == 1 || dbt->brp == 2) {
+ /* Reuse "normal" sample point and convert it to time quanta */
+ u32 sample_point_in_tq = can_bit_time(dbt) * dbt->sample_point / 1000;
+
+ tdc->tdco = min(sample_point_in_tq, tdc_const->tdco_max);
+ } else {
+ tdc->tdco = 0;
+ }
+}
#endif /* CONFIG_CAN_CALC_BITTIMING */
/* Checks the validity of the specified bit-timing parameters prop_seg,
diff --git a/drivers/net/can/dev/netlink.c b/drivers/net/can/dev/netlink.c
index 8443480a703d..e38c2566aff4 100644
--- a/drivers/net/can/dev/netlink.c
+++ b/drivers/net/can/dev/netlink.c
@@ -186,6 +186,8 @@ static int can_changelink(struct net_device *dev, struct nlattr *tb[],
memcpy(&priv->data_bittiming, &dbt, sizeof(dbt));
+ can_calc_tdco(dev);
+
if (priv->do_set_data_bittiming) {
/* Finally, set the bit-timing registers */
err = priv->do_set_data_bittiming(dev);
diff --git a/include/linux/can/bittiming.h b/include/linux/can/bittiming.h
index b31a49f19b47..3c4cad7b52c0 100644
--- a/include/linux/can/bittiming.h
+++ b/include/linux/can/bittiming.h
@@ -78,6 +78,8 @@ struct can_tdc_const {
#ifdef CONFIG_CAN_CALC_BITTIMING
int can_calc_bittiming(struct net_device *dev, struct can_bittiming *bt,
const struct can_bittiming_const *btc);
+
+void can_calc_tdco(struct net_device *dev);
#else /* !CONFIG_CAN_CALC_BITTIMING */
static inline int
can_calc_bittiming(struct net_device *dev, struct can_bittiming *bt,
@@ -86,6 +88,10 @@ can_calc_bittiming(struct net_device *dev, struct can_bittiming *bt,
netdev_err(dev, "bit-timing calculation not available\n");
return -EINVAL;
}
+
+static inline void can_calc_tdco(struct net_device *dev)
+{
+}
#endif /* CONFIG_CAN_CALC_BITTIMING */
int can_get_bittiming(struct net_device *dev, struct can_bittiming *bt,