Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

can: rockchip_canfd: add hardware timestamping support

Add support for hardware based timestamping.

Tested-by: Alibek Omarov <a1ba.omarov@gmail.com>
Acked-by: Heiko Stuebner <heiko@sntech.de>
Link: https://patch.msgid.link/20240904-rockchip-canfd-v5-18-8ae22bcb27cc@pengutronix.de
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>

+115 -3
+6
drivers/net/can/rockchip/rockchip_canfd-core.c
··· 292 292 293 293 rkcanfd_chip_fifo_setup(priv); 294 294 rkcanfd_timestamp_init(priv); 295 + rkcanfd_timestamp_start(priv); 296 + 295 297 rkcanfd_set_bittiming(priv); 296 298 297 299 rkcanfd_chip_interrupts_disable(priv); ··· 317 315 { 318 316 priv->can.state = state; 319 317 318 + rkcanfd_timestamp_stop(priv); 320 319 __rkcanfd_chip_stop(priv, state); 321 320 } 322 321 ··· 325 322 { 326 323 priv->can.state = state; 327 324 325 + rkcanfd_timestamp_stop_sync(priv); 328 326 __rkcanfd_chip_stop(priv, state); 329 327 } 330 328 ··· 357 353 *timestamp = rkcanfd_get_timestamp(priv); 358 354 359 355 skb = alloc_can_err_skb(priv->ndev, cf); 356 + if (skb) 357 + rkcanfd_skb_set_timestamp(priv, skb, *timestamp); 360 358 361 359 return skb; 362 360 }
+1 -1
drivers/net/can/rockchip/rockchip_canfd-ethtool.c
··· 59 59 } 60 60 61 61 static const struct ethtool_ops rkcanfd_ethtool_ops = { 62 - .get_ts_info = ethtool_op_get_ts_info, 62 + .get_ts_info = can_ethtool_op_get_ts_info_hwts, 63 63 .get_strings = rkcanfd_ethtool_get_strings, 64 64 .get_sset_count = rkcanfd_ethtool_get_sset_count, 65 65 .get_ethtool_stats = rkcanfd_ethtool_get_ethtool_stats,
+1
drivers/net/can/rockchip/rockchip_canfd-rx.c
··· 267 267 } 268 268 269 269 memcpy(skb_cfd, cfd, len); 270 + rkcanfd_skb_set_timestamp(priv, skb, header->ts); 270 271 271 272 err = can_rx_offload_queue_timestamp(&priv->offload, skb, header->ts); 272 273 if (err)
+92 -2
drivers/net/can/rockchip/rockchip_canfd-timestamp.c
··· 4 4 // Marc Kleine-Budde <kernel@pengutronix.de> 5 5 // 6 6 7 + #include <linux/clocksource.h> 8 + 7 9 #include "rockchip_canfd.h" 10 + 11 + static u64 rkcanfd_timestamp_read(const struct cyclecounter *cc) 12 + { 13 + const struct rkcanfd_priv *priv = container_of(cc, struct rkcanfd_priv, cc); 14 + 15 + return rkcanfd_get_timestamp(priv); 16 + } 17 + 18 + void rkcanfd_skb_set_timestamp(const struct rkcanfd_priv *priv, 19 + struct sk_buff *skb, const u32 timestamp) 20 + { 21 + struct skb_shared_hwtstamps *hwtstamps = skb_hwtstamps(skb); 22 + u64 ns; 23 + 24 + ns = timecounter_cyc2time(&priv->tc, timestamp); 25 + 26 + hwtstamps->hwtstamp = ns_to_ktime(ns); 27 + } 28 + 29 + static void rkcanfd_timestamp_work(struct work_struct *work) 30 + { 31 + const struct delayed_work *delayed_work = to_delayed_work(work); 32 + struct rkcanfd_priv *priv; 33 + 34 + priv = container_of(delayed_work, struct rkcanfd_priv, timestamp); 35 + timecounter_read(&priv->tc); 36 + 37 + schedule_delayed_work(&priv->timestamp, priv->work_delay_jiffies); 38 + } 8 39 9 40 void rkcanfd_timestamp_init(struct rkcanfd_priv *priv) 10 41 { 11 - u32 reg; 42 + const struct can_bittiming *dbt = &priv->can.data_bittiming; 43 + const struct can_bittiming *bt = &priv->can.bittiming; 44 + struct cyclecounter *cc = &priv->cc; 45 + u32 bitrate, div, reg, rate; 46 + u64 work_delay_ns; 47 + u64 max_cycles; 12 48 13 - reg = RKCANFD_REG_TIMESTAMP_CTRL_TIME_BASE_COUNTER_ENABLE; 49 + /* At the standard clock rate of 300Mhz on the rk3658, the 32 50 + * bit timer overflows every 14s. This means that we have to 51 + * poll it quite often to avoid missing a wrap around. 52 + * 53 + * Divide it down to a reasonable rate, at least twice the bit 54 + * rate. 55 + */ 56 + bitrate = max(bt->bitrate, dbt->bitrate); 57 + div = min(DIV_ROUND_UP(priv->can.clock.freq, bitrate * 2), 58 + FIELD_MAX(RKCANFD_REG_TIMESTAMP_CTRL_TIME_BASE_COUNTER_PRESCALE) + 1); 59 + 60 + reg = FIELD_PREP(RKCANFD_REG_TIMESTAMP_CTRL_TIME_BASE_COUNTER_PRESCALE, 61 + div - 1) | 62 + RKCANFD_REG_TIMESTAMP_CTRL_TIME_BASE_COUNTER_ENABLE; 14 63 rkcanfd_write(priv, RKCANFD_REG_TIMESTAMP_CTRL, reg); 64 + 65 + cc->read = rkcanfd_timestamp_read; 66 + cc->mask = CYCLECOUNTER_MASK(32); 67 + 68 + rate = priv->can.clock.freq / div; 69 + clocks_calc_mult_shift(&cc->mult, &cc->shift, rate, NSEC_PER_SEC, 70 + RKCANFD_TIMESTAMP_WORK_MAX_DELAY_SEC); 71 + 72 + max_cycles = div_u64(ULLONG_MAX, cc->mult); 73 + max_cycles = min(max_cycles, cc->mask); 74 + work_delay_ns = clocksource_cyc2ns(max_cycles, cc->mult, cc->shift) / 3; 75 + priv->work_delay_jiffies = nsecs_to_jiffies(work_delay_ns); 76 + INIT_DELAYED_WORK(&priv->timestamp, rkcanfd_timestamp_work); 77 + 78 + netdev_dbg(priv->ndev, "clock=%lu.%02luMHz bitrate=%lu.%02luMBit/s div=%u rate=%lu.%02luMHz mult=%u shift=%u delay=%lus\n", 79 + priv->can.clock.freq / MEGA, 80 + priv->can.clock.freq % MEGA / KILO / 10, 81 + bitrate / MEGA, 82 + bitrate % MEGA / KILO / 100, 83 + div, 84 + rate / MEGA, 85 + rate % MEGA / KILO / 10, 86 + cc->mult, cc->shift, 87 + priv->work_delay_jiffies / HZ); 88 + } 89 + 90 + void rkcanfd_timestamp_start(struct rkcanfd_priv *priv) 91 + { 92 + timecounter_init(&priv->tc, &priv->cc, ktime_get_real_ns()); 93 + 94 + schedule_delayed_work(&priv->timestamp, priv->work_delay_jiffies); 95 + } 96 + 97 + void rkcanfd_timestamp_stop(struct rkcanfd_priv *priv) 98 + { 99 + cancel_delayed_work(&priv->timestamp); 100 + } 101 + 102 + void rkcanfd_timestamp_stop_sync(struct rkcanfd_priv *priv) 103 + { 104 + cancel_delayed_work_sync(&priv->timestamp); 15 105 }
+4
drivers/net/can/rockchip/rockchip_canfd-tx.c
··· 145 145 { 146 146 struct net_device_stats *stats = &priv->ndev->stats; 147 147 unsigned int tx_tail; 148 + struct sk_buff *skb; 148 149 149 150 tx_tail = rkcanfd_get_tx_tail(priv); 151 + skb = priv->can.echo_skb[tx_tail]; 150 152 151 153 /* Manual handling of CAN Bus Error counters. See 152 154 * rkcanfd_get_corrected_berr_counter() for detailed ··· 157 155 if (priv->bec.txerr) 158 156 priv->bec.txerr--; 159 157 158 + if (skb) 159 + rkcanfd_skb_set_timestamp(priv, skb, ts); 160 160 stats->tx_bytes += 161 161 can_rx_offload_get_echo_skb_queue_timestamp(&priv->offload, 162 162 tx_tail, ts,
+11
drivers/net/can/rockchip/rockchip_canfd.h
··· 15 15 #include <linux/netdevice.h> 16 16 #include <linux/reset.h> 17 17 #include <linux/skbuff.h> 18 + #include <linux/timecounter.h> 18 19 #include <linux/types.h> 19 20 #include <linux/u64_stats_sync.h> 20 21 #include <linux/units.h> ··· 470 469 u32 reg_int_mask_default; 471 470 struct rkcanfd_devtype_data devtype_data; 472 471 472 + struct cyclecounter cc; 473 + struct timecounter tc; 474 + struct delayed_work timestamp; 475 + unsigned long work_delay_jiffies; 476 + 473 477 struct can_berr_counter bec; 474 478 475 479 struct rkcanfd_stats stats; ··· 537 531 538 532 int rkcanfd_handle_rx_int(struct rkcanfd_priv *priv); 539 533 534 + void rkcanfd_skb_set_timestamp(const struct rkcanfd_priv *priv, 535 + struct sk_buff *skb, const u32 timestamp); 540 536 void rkcanfd_timestamp_init(struct rkcanfd_priv *priv); 537 + void rkcanfd_timestamp_start(struct rkcanfd_priv *priv); 538 + void rkcanfd_timestamp_stop(struct rkcanfd_priv *priv); 539 + void rkcanfd_timestamp_stop_sync(struct rkcanfd_priv *priv); 541 540 542 541 unsigned int rkcanfd_get_effective_tx_free(const struct rkcanfd_priv *priv); 543 542 void rkcanfd_xmit_retry(struct rkcanfd_priv *priv);