]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
can: kvaser_usb: leaf: Add hardware timestamp support to usbcan devices
authorJimmy Assarsson <extja@kvaser.com>
Mon, 1 Jul 2024 15:49:33 +0000 (17:49 +0200)
committerMarc Kleine-Budde <mkl@pengutronix.de>
Mon, 5 Aug 2024 15:39:02 +0000 (17:39 +0200)
Add hardware timestamp support for all usbcan based devices (M16C).
The usbcan firmware is slightly different compared to the other Kvaser USB
interfaces:
  - The timestamp is provided by a 32-bit counter, with 10us resolution.
    Hence, the hardware timestamp will wrap after less than 12 hours.
  - Each Rx CAN or Tx ACK command only contains the 16-bits LSB of the
    timestamp counter.
  - The 16-bits MSB are sent in an asynchronous event (command), if any
    change occurred in the MSB since the last event.

Signed-off-by: Jimmy Assarsson <extja@kvaser.com>
Reviewed-by: Vincent Mailhol <mailhol.vincent@wanadoo.fr>
Link: https://lore.kernel.org/all/20240701154936.92633-13-extja@kvaser.com
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
drivers/net/can/usb/kvaser_usb/kvaser_usb_core.c
drivers/net/can/usb/kvaser_usb/kvaser_usb_leaf.c

index b5d762d38d5d63ac2fec2f381253b742a1f1c370..576ddf932f47ec2b6615c5ad16882e56689c8f80 100644 (file)
@@ -100,7 +100,8 @@ static const struct kvaser_usb_driver_info kvaser_usb_driver_info_hydra = {
 
 static const struct kvaser_usb_driver_info kvaser_usb_driver_info_usbcan = {
        .quirks = KVASER_USB_QUIRK_HAS_TXRX_ERRORS |
-                 KVASER_USB_QUIRK_HAS_SILENT_MODE,
+                 KVASER_USB_QUIRK_HAS_SILENT_MODE |
+                 KVASER_USB_QUIRK_HAS_HARDWARE_TIMESTAMP,
        .family = KVASER_USBCAN,
        .ops = &kvaser_usb_leaf_dev_ops,
 };
index 465707174f2eea249b92c6a7e8e83aeff27555d9..6b9122ab1464f9c85e5d0e320efa3501c4bc3912 100644 (file)
 
 /* USBCanII timestamp */
 #define KVASER_USB_USBCAN_CLK_OVERFLOW_MASK GENMASK(31, 16)
+#define KVASER_USB_USBCAN_TIMESTAMP_FACTOR 10
 
 struct kvaser_cmd_simple {
        u8 tid;
@@ -536,6 +537,15 @@ static const struct kvaser_usb_dev_cfg kvaser_usb_leaf_imx_dev_cfg_32mhz = {
        .bittiming_const = &kvaser_usb_flexc_bittiming_const,
 };
 
+static inline ktime_t kvaser_usb_usbcan_timestamp_to_ktime(const struct kvaser_usb *dev,
+                                                          __le16 timestamp)
+{
+       u64 ticks = le16_to_cpu(timestamp) |
+                   dev->card_data.usbcan_timestamp_msb;
+
+       return kvaser_usb_ticks_to_ktime(dev->cfg, ticks * KVASER_USB_USBCAN_TIMESTAMP_FACTOR);
+}
+
 static int kvaser_usb_leaf_verify_size(const struct kvaser_usb *dev,
                                       const struct kvaser_cmd *cmd)
 {
@@ -978,6 +988,7 @@ static void kvaser_usb_leaf_tx_acknowledge(const struct kvaser_usb *dev,
                hwtstamp = kvaser_usb_timestamp48_to_ktime(dev->cfg, cmd->u.leaf.tx_ack.time);
                break;
        case KVASER_USBCAN:
+               hwtstamp = kvaser_usb_usbcan_timestamp_to_ktime(dev, cmd->u.usbcan.tx_ack.time);
                break;
        }
 
@@ -1398,6 +1409,7 @@ static void kvaser_usb_leaf_rx_can_msg(const struct kvaser_usb *dev,
                break;
        case KVASER_USBCAN:
                rx_data = cmd->u.usbcan.rx_can.data;
+               hwtstamp = kvaser_usb_usbcan_timestamp_to_ktime(dev, cmd->u.usbcan.rx_can.time);
                break;
        }