Commit 2c14119a authored by Jakub Kicinski's avatar Jakub Kicinski

Merge tag 'linux-can-next-for-6.12-20240806' of...

Merge tag 'linux-can-next-for-6.12-20240806' of git://git.kernel.org/pub/scm/linux/kernel/git/mkl/linux-can-next

Marc Kleine-Budde says:

====================
pull-request: can-next 2024-08-06

The first patch is by Frank Li and adds the can-transceiver property
to the flexcan device-tree bindings.

Haibo Chen contributes 2 patches for the flexcan driver to add wakeup
support for the imx95.

The 2 patches by Stefan Mätje for the esd_402_pci driver clean up the
driver and add support for the one-shot mode.

The last 15 patches are by Jimmy Assarsson and add hardware timestamp
support for all devices covered by the kvaser_usb driver.

* tag 'linux-can-next-for-6.12-20240806' of git://git.kernel.org/pub/scm/linux/kernel/git/mkl/linux-can-next:
  can: kvaser_usb: Rename kvaser_usb_{ethtool,netdev}_ops_hwts to kvaser_usb_{ethtool,netdev}_ops
  can: kvaser_usb: Remove struct variables kvaser_usb_{ethtool,netdev}_ops
  can: kvaser_usb: Remove KVASER_USB_QUIRK_HAS_HARDWARE_TIMESTAMP
  can: kvaser_usb: leaf: Add hardware timestamp support to usbcan devices
  can: kvaser_usb: leaf: Store MSB of timestamp
  can: kvaser_usb: leaf: Add structs for Tx ACK and clock overflow commands
  can: kvaser_usb: leaf: Add hardware timestamp support to leaf based devices
  can: kvaser_usb: leaf: kvaser_usb_leaf_tx_acknowledge: Rename local variable
  can: kvaser_usb: leaf: Replace kvaser_usb_leaf_m32c_dev_cfg with kvaser_usb_leaf_m32c_dev_cfg_{16,24,32}mhz
  can: kvaser_usb: leaf: Assign correct timestamp_freq for kvaser_usb_leaf_imx_dev_cfg_{16,24,32}mhz
  can: kvaser_usb: leaf: Add struct for Tx ACK commands
  can: kvaser_usb: hydra: Set hardware timestamp on transmitted packets
  can: kvaser_usb: hydra: Add struct for Tx ACK commands
  can: kvaser_usb: hydra: kvaser_usb_hydra_ktime_from_rx_cmd: Drop {rx_} in function name
  can: kvaser_usb: Add helper functions to convert device timestamp into ktime
  can: esd_402_pci: Add support for one-shot mode
  can: esd_402_pci: Rename esdACC CTRL register macros
  can: flexcan: add wakeup support for imx95
  dt-bindings: can: fsl,flexcan: move fsl,imx95-flexcan standalone
  dt-bindings: can: fsl,flexcan: add common 'can-transceiver' for fsl,flexcan
====================

Link: https://patch.msgid.link/20240806074731.1905378-1-mkl@pengutronix.deSigned-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parents acd221a6 fa3c40b9
......@@ -17,6 +17,7 @@ properties:
compatible:
oneOf:
- enum:
- fsl,imx95-flexcan
- fsl,imx93-flexcan
- fsl,imx8qm-flexcan
- fsl,imx8mp-flexcan
......@@ -38,9 +39,6 @@ properties:
- fsl,imx6ul-flexcan
- fsl,imx6sx-flexcan
- const: fsl,imx6q-flexcan
- items:
- const: fsl,imx95-flexcan
- const: fsl,imx93-flexcan
- items:
- enum:
- fsl,ls1028ar1-flexcan
......@@ -80,6 +78,10 @@ properties:
node then controller is assumed to be little endian. If this property is
present then controller is assumed to be big endian.
can-transceiver:
$ref: can-transceiver.yaml#
unevaluatedProperties: false
fsl,stop-mode:
description: |
Register bits of stop mode control.
......
......@@ -369,12 +369,13 @@ static int pci402_init_cores(struct pci_dev *pdev)
SET_NETDEV_DEV(netdev, &pdev->dev);
priv = netdev_priv(netdev);
priv->can.clock.freq = card->ov.core_frequency;
priv->can.ctrlmode_supported = CAN_CTRLMODE_LOOPBACK |
CAN_CTRLMODE_LISTENONLY |
CAN_CTRLMODE_BERR_REPORTING |
CAN_CTRLMODE_CC_LEN8_DLC;
priv->can.clock.freq = card->ov.core_frequency;
if (card->ov.features & ACC_OV_REG_FEAT_MASK_DAR)
priv->can.ctrlmode_supported |= CAN_CTRLMODE_ONE_SHOT;
if (card->ov.features & ACC_OV_REG_FEAT_MASK_CANFD)
priv->can.bittiming_const = &pci402_bittiming_const_canfd;
else
......
......@@ -17,6 +17,9 @@
/* esdACC DLC register layout */
#define ACC_DLC_DLC_MASK GENMASK(3, 0)
#define ACC_DLC_RTR_FLAG BIT(4)
#define ACC_DLC_SSTX_FLAG BIT(24) /* Single Shot TX */
/* esdACC DLC in struct acc_bmmsg_rxtxdone::acc_dlc.len only! */
#define ACC_DLC_TXD_FLAG BIT(5)
/* ecc value of esdACC equals SJA1000's ECC register */
......@@ -43,8 +46,8 @@
static void acc_resetmode_enter(struct acc_core *core)
{
acc_set_bits(core, ACC_CORE_OF_CTRL_MODE,
ACC_REG_CONTROL_MASK_MODE_RESETMODE);
acc_set_bits(core, ACC_CORE_OF_CTRL,
ACC_REG_CTRL_MASK_RESETMODE);
/* Read back reset mode bit to flush PCI write posting */
acc_resetmode_entered(core);
......@@ -52,14 +55,14 @@ static void acc_resetmode_enter(struct acc_core *core)
static void acc_resetmode_leave(struct acc_core *core)
{
acc_clear_bits(core, ACC_CORE_OF_CTRL_MODE,
ACC_REG_CONTROL_MASK_MODE_RESETMODE);
acc_clear_bits(core, ACC_CORE_OF_CTRL,
ACC_REG_CTRL_MASK_RESETMODE);
/* Read back reset mode bit to flush PCI write posting */
acc_resetmode_entered(core);
}
static void acc_txq_put(struct acc_core *core, u32 acc_id, u8 acc_dlc,
static void acc_txq_put(struct acc_core *core, u32 acc_id, u32 acc_dlc,
const void *data)
{
acc_write32_noswap(core, ACC_CORE_OF_TXFIFO_DATA_1,
......@@ -172,7 +175,7 @@ int acc_open(struct net_device *netdev)
struct acc_net_priv *priv = netdev_priv(netdev);
struct acc_core *core = priv->core;
u32 tx_fifo_status;
u32 ctrl_mode;
u32 ctrl;
int err;
/* Retry to enter RESET mode if out of sync. */
......@@ -187,19 +190,19 @@ int acc_open(struct net_device *netdev)
if (err)
return err;
ctrl_mode = ACC_REG_CONTROL_MASK_IE_RXTX |
ACC_REG_CONTROL_MASK_IE_TXERROR |
ACC_REG_CONTROL_MASK_IE_ERRWARN |
ACC_REG_CONTROL_MASK_IE_OVERRUN |
ACC_REG_CONTROL_MASK_IE_ERRPASS;
ctrl = ACC_REG_CTRL_MASK_IE_RXTX |
ACC_REG_CTRL_MASK_IE_TXERROR |
ACC_REG_CTRL_MASK_IE_ERRWARN |
ACC_REG_CTRL_MASK_IE_OVERRUN |
ACC_REG_CTRL_MASK_IE_ERRPASS;
if (priv->can.ctrlmode & CAN_CTRLMODE_BERR_REPORTING)
ctrl_mode |= ACC_REG_CONTROL_MASK_IE_BUSERR;
ctrl |= ACC_REG_CTRL_MASK_IE_BUSERR;
if (priv->can.ctrlmode & CAN_CTRLMODE_LISTENONLY)
ctrl_mode |= ACC_REG_CONTROL_MASK_MODE_LOM;
ctrl |= ACC_REG_CTRL_MASK_LOM;
acc_set_bits(core, ACC_CORE_OF_CTRL_MODE, ctrl_mode);
acc_set_bits(core, ACC_CORE_OF_CTRL, ctrl);
acc_resetmode_leave(core);
priv->can.state = CAN_STATE_ERROR_ACTIVE;
......@@ -218,13 +221,13 @@ int acc_close(struct net_device *netdev)
struct acc_net_priv *priv = netdev_priv(netdev);
struct acc_core *core = priv->core;
acc_clear_bits(core, ACC_CORE_OF_CTRL_MODE,
ACC_REG_CONTROL_MASK_IE_RXTX |
ACC_REG_CONTROL_MASK_IE_TXERROR |
ACC_REG_CONTROL_MASK_IE_ERRWARN |
ACC_REG_CONTROL_MASK_IE_OVERRUN |
ACC_REG_CONTROL_MASK_IE_ERRPASS |
ACC_REG_CONTROL_MASK_IE_BUSERR);
acc_clear_bits(core, ACC_CORE_OF_CTRL,
ACC_REG_CTRL_MASK_IE_RXTX |
ACC_REG_CTRL_MASK_IE_TXERROR |
ACC_REG_CTRL_MASK_IE_ERRWARN |
ACC_REG_CTRL_MASK_IE_OVERRUN |
ACC_REG_CTRL_MASK_IE_ERRPASS |
ACC_REG_CTRL_MASK_IE_BUSERR);
netif_stop_queue(netdev);
acc_resetmode_enter(core);
......@@ -233,9 +236,9 @@ int acc_close(struct net_device *netdev)
/* Mark pending TX requests to be aborted after controller restart. */
acc_write32(core, ACC_CORE_OF_TX_ABORT_MASK, 0xffff);
/* ACC_REG_CONTROL_MASK_MODE_LOM is only accessible in RESET mode */
acc_clear_bits(core, ACC_CORE_OF_CTRL_MODE,
ACC_REG_CONTROL_MASK_MODE_LOM);
/* ACC_REG_CTRL_MASK_LOM is only accessible in RESET mode */
acc_clear_bits(core, ACC_CORE_OF_CTRL,
ACC_REG_CTRL_MASK_LOM);
close_candev(netdev);
return 0;
......@@ -249,7 +252,7 @@ netdev_tx_t acc_start_xmit(struct sk_buff *skb, struct net_device *netdev)
u8 tx_fifo_head = core->tx_fifo_head;
int fifo_usage;
u32 acc_id;
u8 acc_dlc;
u32 acc_dlc;
if (can_dropped_invalid_skb(netdev, skb))
return NETDEV_TX_OK;
......@@ -274,6 +277,8 @@ netdev_tx_t acc_start_xmit(struct sk_buff *skb, struct net_device *netdev)
acc_dlc = can_get_cc_dlc(cf, priv->can.ctrlmode);
if (cf->can_id & CAN_RTR_FLAG)
acc_dlc |= ACC_DLC_RTR_FLAG;
if (priv->can.ctrlmode & CAN_CTRLMODE_ONE_SHOT)
acc_dlc |= ACC_DLC_SSTX_FLAG;
if (cf->can_id & CAN_EFF_FLAG) {
acc_id = cf->can_id & CAN_EFF_MASK;
......
......@@ -35,6 +35,7 @@
*/
#define ACC_OV_REG_FEAT_MASK_CANFD BIT(27 - 16)
#define ACC_OV_REG_FEAT_MASK_NEW_PSC BIT(28 - 16)
#define ACC_OV_REG_FEAT_MASK_DAR BIT(30 - 16)
#define ACC_OV_REG_MODE_MASK_ENDIAN_LITTLE BIT(0)
#define ACC_OV_REG_MODE_MASK_BM_ENABLE BIT(1)
......@@ -50,7 +51,7 @@
#define ACC_OV_REG_MODE_MASK_FPGA_RESET BIT(31)
/* esdACC CAN Core Module */
#define ACC_CORE_OF_CTRL_MODE 0x0000
#define ACC_CORE_OF_CTRL 0x0000
#define ACC_CORE_OF_STATUS_IRQ 0x0008
#define ACC_CORE_OF_BRP 0x000c
#define ACC_CORE_OF_BTR 0x0010
......@@ -66,21 +67,22 @@
#define ACC_CORE_OF_TXFIFO_DATA_0 0x00c8
#define ACC_CORE_OF_TXFIFO_DATA_1 0x00cc
#define ACC_REG_CONTROL_MASK_MODE_RESETMODE BIT(0)
#define ACC_REG_CONTROL_MASK_MODE_LOM BIT(1)
#define ACC_REG_CONTROL_MASK_MODE_STM BIT(2)
#define ACC_REG_CONTROL_MASK_MODE_TRANSEN BIT(5)
#define ACC_REG_CONTROL_MASK_MODE_TS BIT(6)
#define ACC_REG_CONTROL_MASK_MODE_SCHEDULE BIT(7)
#define ACC_REG_CONTROL_MASK_IE_RXTX BIT(8)
#define ACC_REG_CONTROL_MASK_IE_TXERROR BIT(9)
#define ACC_REG_CONTROL_MASK_IE_ERRWARN BIT(10)
#define ACC_REG_CONTROL_MASK_IE_OVERRUN BIT(11)
#define ACC_REG_CONTROL_MASK_IE_TSI BIT(12)
#define ACC_REG_CONTROL_MASK_IE_ERRPASS BIT(13)
#define ACC_REG_CONTROL_MASK_IE_ALI BIT(14)
#define ACC_REG_CONTROL_MASK_IE_BUSERR BIT(15)
/* CTRL register layout */
#define ACC_REG_CTRL_MASK_RESETMODE BIT(0)
#define ACC_REG_CTRL_MASK_LOM BIT(1)
#define ACC_REG_CTRL_MASK_STM BIT(2)
#define ACC_REG_CTRL_MASK_TRANSEN BIT(5)
#define ACC_REG_CTRL_MASK_TS BIT(6)
#define ACC_REG_CTRL_MASK_SCHEDULE BIT(7)
#define ACC_REG_CTRL_MASK_IE_RXTX BIT(8)
#define ACC_REG_CTRL_MASK_IE_TXERROR BIT(9)
#define ACC_REG_CTRL_MASK_IE_ERRWARN BIT(10)
#define ACC_REG_CTRL_MASK_IE_OVERRUN BIT(11)
#define ACC_REG_CTRL_MASK_IE_TSI BIT(12)
#define ACC_REG_CTRL_MASK_IE_ERRPASS BIT(13)
#define ACC_REG_CTRL_MASK_IE_ALI BIT(14)
#define ACC_REG_CTRL_MASK_IE_BUSERR BIT(15)
/* BRP and BTR register layout for CAN-Classic version */
#define ACC_REG_BRP_CL_MASK_BRP GENMASK(8, 0)
......@@ -300,9 +302,9 @@ static inline void acc_clear_bits(struct acc_core *core,
static inline int acc_resetmode_entered(struct acc_core *core)
{
u32 ctrl = acc_read32(core, ACC_CORE_OF_CTRL_MODE);
u32 ctrl = acc_read32(core, ACC_CORE_OF_CTRL);
return (ctrl & ACC_REG_CONTROL_MASK_MODE_RESETMODE) != 0;
return (ctrl & ACC_REG_CTRL_MASK_RESETMODE) != 0;
}
static inline u32 acc_ov_read32(struct acc_ov *ov, unsigned short offs)
......
......@@ -354,6 +354,14 @@ static struct flexcan_devtype_data fsl_imx93_devtype_data = {
FLEXCAN_QUIRK_SUPPORT_RX_MAILBOX_RTR,
};
static const struct flexcan_devtype_data fsl_imx95_devtype_data = {
.quirks = FLEXCAN_QUIRK_DISABLE_RXFG | FLEXCAN_QUIRK_ENABLE_EACEN_RRS |
FLEXCAN_QUIRK_DISABLE_MECR | FLEXCAN_QUIRK_USE_RX_MAILBOX |
FLEXCAN_QUIRK_BROKEN_PERR_STATE | FLEXCAN_QUIRK_SUPPORT_FD |
FLEXCAN_QUIRK_SUPPORT_ECC | FLEXCAN_QUIRK_SUPPORT_RX_MAILBOX |
FLEXCAN_QUIRK_SUPPORT_RX_MAILBOX_RTR | FLEXCAN_QUIRK_SETUP_STOP_MODE_SCMI,
};
static const struct flexcan_devtype_data fsl_vf610_devtype_data = {
.quirks = FLEXCAN_QUIRK_DISABLE_RXFG | FLEXCAN_QUIRK_ENABLE_EACEN_RRS |
FLEXCAN_QUIRK_DISABLE_MECR | FLEXCAN_QUIRK_USE_RX_MAILBOX |
......@@ -544,6 +552,13 @@ static inline int flexcan_enter_stop_mode(struct flexcan_priv *priv)
} else if (priv->devtype_data.quirks & FLEXCAN_QUIRK_SETUP_STOP_MODE_GPR) {
regmap_update_bits(priv->stm.gpr, priv->stm.req_gpr,
1 << priv->stm.req_bit, 1 << priv->stm.req_bit);
} else if (priv->devtype_data.quirks & FLEXCAN_QUIRK_SETUP_STOP_MODE_SCMI) {
/* For the SCMI mode, driver do nothing, ATF will send request to
* SM(system manager, M33 core) through SCMI protocol after linux
* suspend. Once SM get this request, it will send IPG_STOP signal
* to Flex_CAN, let CAN in STOP mode.
*/
return 0;
}
return flexcan_low_power_enter_ack(priv);
......@@ -555,7 +570,11 @@ static inline int flexcan_exit_stop_mode(struct flexcan_priv *priv)
u32 reg_mcr;
int ret;
/* remove stop request */
/* Remove stop request, for FLEXCAN_QUIRK_SETUP_STOP_MODE_SCMI,
* do nothing here, because ATF already send request to SM before
* linux resume. Once SM get this request, it will deassert the
* IPG_STOP signal to Flex_CAN.
*/
if (priv->devtype_data.quirks & FLEXCAN_QUIRK_SETUP_STOP_MODE_SCFW) {
ret = flexcan_stop_mode_enable_scfw(priv, false);
if (ret < 0)
......@@ -1983,6 +2002,9 @@ static int flexcan_setup_stop_mode(struct platform_device *pdev)
ret = flexcan_setup_stop_mode_scfw(pdev);
else if (priv->devtype_data.quirks & FLEXCAN_QUIRK_SETUP_STOP_MODE_GPR)
ret = flexcan_setup_stop_mode_gpr(pdev);
else if (priv->devtype_data.quirks & FLEXCAN_QUIRK_SETUP_STOP_MODE_SCMI)
/* ATF will handle all STOP_IPG related work */
ret = 0;
else
/* return 0 directly if doesn't support stop mode feature */
return 0;
......@@ -2009,6 +2031,7 @@ static const struct of_device_id flexcan_of_match[] = {
{ .compatible = "fsl,imx8qm-flexcan", .data = &fsl_imx8qm_devtype_data, },
{ .compatible = "fsl,imx8mp-flexcan", .data = &fsl_imx8mp_devtype_data, },
{ .compatible = "fsl,imx93-flexcan", .data = &fsl_imx93_devtype_data, },
{ .compatible = "fsl,imx95-flexcan", .data = &fsl_imx95_devtype_data, },
{ .compatible = "fsl,imx6q-flexcan", .data = &fsl_imx6q_devtype_data, },
{ .compatible = "fsl,imx28-flexcan", .data = &fsl_imx28_devtype_data, },
{ .compatible = "fsl,imx53-flexcan", .data = &fsl_imx25_devtype_data, },
......@@ -2309,9 +2332,19 @@ static int __maybe_unused flexcan_noirq_suspend(struct device *device)
if (device_may_wakeup(device))
flexcan_enable_wakeup_irq(priv, true);
err = pm_runtime_force_suspend(device);
if (err)
return err;
/* For FLEXCAN_QUIRK_SETUP_STOP_MODE_SCMI, it need ATF to send
* to SM through SCMI protocol, SM will assert the IPG_STOP
* signal. But all this works need the CAN clocks keep on.
* After the CAN module get the IPG_STOP mode, and switch to
* STOP mode, whether still keep the CAN clocks on or gate them
* off depend on the Hardware design.
*/
if (!(device_may_wakeup(device) &&
priv->devtype_data.quirks & FLEXCAN_QUIRK_SETUP_STOP_MODE_SCMI)) {
err = pm_runtime_force_suspend(device);
if (err)
return err;
}
}
return 0;
......@@ -2325,9 +2358,12 @@ static int __maybe_unused flexcan_noirq_resume(struct device *device)
if (netif_running(dev)) {
int err;
err = pm_runtime_force_resume(device);
if (err)
return err;
if (!(device_may_wakeup(device) &&
priv->devtype_data.quirks & FLEXCAN_QUIRK_SETUP_STOP_MODE_SCMI)) {
err = pm_runtime_force_resume(device);
if (err)
return err;
}
if (device_may_wakeup(device))
flexcan_enable_wakeup_irq(priv, false);
......
......@@ -68,6 +68,8 @@
#define FLEXCAN_QUIRK_SUPPORT_RX_MAILBOX_RTR BIT(15)
/* Device supports RX via FIFO */
#define FLEXCAN_QUIRK_SUPPORT_RX_FIFO BIT(16)
/* Setup stop mode with ATF SCMI protocol to support wakeup */
#define FLEXCAN_QUIRK_SETUP_STOP_MODE_SCMI BIT(17)
struct flexcan_devtype_data {
u32 quirks; /* quirks needed for different IP cores */
......
......@@ -22,6 +22,8 @@
*/
#include <linux/completion.h>
#include <linux/ktime.h>
#include <linux/math64.h>
#include <linux/spinlock.h>
#include <linux/types.h>
#include <linux/usb.h>
......@@ -39,7 +41,6 @@
#define KVASER_USB_QUIRK_HAS_SILENT_MODE BIT(0)
#define KVASER_USB_QUIRK_HAS_TXRX_ERRORS BIT(1)
#define KVASER_USB_QUIRK_IGNORE_CLK_FREQ BIT(2)
#define KVASER_USB_QUIRK_HAS_HARDWARE_TIMESTAMP BIT(3)
/* Device capabilities */
#define KVASER_USB_CAP_BERR_CAP 0x01
......@@ -68,6 +69,7 @@ struct kvaser_usb_dev_card_data {
u32 ctrlmode_supported;
u32 capabilities;
struct kvaser_usb_dev_card_data_hydra hydra;
u32 usbcan_timestamp_msb;
};
/* Context for an outstanding, not yet ACKed, transmission */
......@@ -216,4 +218,26 @@ int kvaser_usb_can_rx_over_error(struct net_device *netdev);
extern const struct can_bittiming_const kvaser_usb_flexc_bittiming_const;
static inline ktime_t kvaser_usb_ticks_to_ktime(const struct kvaser_usb_dev_cfg *cfg,
u64 ticks)
{
return ns_to_ktime(div_u64(ticks * 1000, cfg->timestamp_freq));
}
static inline ktime_t kvaser_usb_timestamp48_to_ktime(const struct kvaser_usb_dev_cfg *cfg,
const __le16 *timestamp)
{
u64 ticks = le16_to_cpu(timestamp[0]) |
(u64)(le16_to_cpu(timestamp[1])) << 16 |
(u64)(le16_to_cpu(timestamp[2])) << 32;
return kvaser_usb_ticks_to_ktime(cfg, ticks);
}
static inline ktime_t kvaser_usb_timestamp64_to_ktime(const struct kvaser_usb_dev_cfg *cfg,
__le64 timestamp)
{
return kvaser_usb_ticks_to_ktime(cfg, le64_to_cpu(timestamp));
}
#endif /* KVASER_USB_H */
......@@ -94,7 +94,7 @@
#define USB_MINI_PCIE_1XCAN_PRODUCT_ID 0x011B
static const struct kvaser_usb_driver_info kvaser_usb_driver_info_hydra = {
.quirks = KVASER_USB_QUIRK_HAS_HARDWARE_TIMESTAMP,
.quirks = 0,
.ops = &kvaser_usb_hydra_dev_ops,
};
......@@ -754,13 +754,6 @@ static netdev_tx_t kvaser_usb_start_xmit(struct sk_buff *skb,
}
static const struct net_device_ops kvaser_usb_netdev_ops = {
.ndo_open = kvaser_usb_open,
.ndo_stop = kvaser_usb_close,
.ndo_start_xmit = kvaser_usb_start_xmit,
.ndo_change_mtu = can_change_mtu,
};
static const struct net_device_ops kvaser_usb_netdev_ops_hwts = {
.ndo_open = kvaser_usb_open,
.ndo_stop = kvaser_usb_close,
.ndo_eth_ioctl = can_eth_ioctl_hwts,
......@@ -769,10 +762,6 @@ static const struct net_device_ops kvaser_usb_netdev_ops_hwts = {
};
static const struct ethtool_ops kvaser_usb_ethtool_ops = {
.get_ts_info = ethtool_op_get_ts_info,
};
static const struct ethtool_ops kvaser_usb_ethtool_ops_hwts = {
.get_ts_info = can_ethtool_op_get_ts_info_hwts,
};
......@@ -859,13 +848,7 @@ static int kvaser_usb_init_one(struct kvaser_usb *dev, int channel)
netdev->flags |= IFF_ECHO;
netdev->netdev_ops = &kvaser_usb_netdev_ops;
if (driver_info->quirks & KVASER_USB_QUIRK_HAS_HARDWARE_TIMESTAMP) {
netdev->netdev_ops = &kvaser_usb_netdev_ops_hwts;
netdev->ethtool_ops = &kvaser_usb_ethtool_ops_hwts;
} else {
netdev->netdev_ops = &kvaser_usb_netdev_ops;
netdev->ethtool_ops = &kvaser_usb_ethtool_ops;
}
netdev->ethtool_ops = &kvaser_usb_ethtool_ops;
SET_NETDEV_DEV(netdev, &dev->intf->dev);
netdev->dev_id = channel;
......
......@@ -10,7 +10,6 @@
* - Transition from CAN_STATE_ERROR_WARNING to CAN_STATE_ERROR_ACTIVE is only
* reported after a call to do_get_berr_counter(), since firmware does not
* distinguish between ERROR_WARNING and ERROR_ACTIVE.
* - Hardware timestamps are not set for CAN Tx frames.
*/
#include <linux/completion.h>
......@@ -261,6 +260,15 @@ struct kvaser_cmd_tx_can {
u8 reserved[11];
} __packed;
struct kvaser_cmd_tx_ack {
__le32 id;
u8 data[8];
u8 dlc;
u8 flags;
__le16 timestamp[3];
u8 reserved0[8];
} __packed;
struct kvaser_cmd_header {
u8 cmd_no;
/* The destination HE address is stored in 0..5 of he_addr.
......@@ -297,6 +305,7 @@ struct kvaser_cmd {
struct kvaser_cmd_rx_can rx_can;
struct kvaser_cmd_tx_can tx_can;
struct kvaser_cmd_tx_ack tx_ack;
} __packed;
} __packed;
......@@ -522,23 +531,25 @@ kvaser_usb_hydra_net_priv_from_cmd(const struct kvaser_usb *dev,
return priv;
}
static ktime_t
kvaser_usb_hydra_ktime_from_rx_cmd(const struct kvaser_usb_dev_cfg *cfg,
const struct kvaser_cmd *cmd)
static ktime_t kvaser_usb_hydra_ktime_from_cmd(const struct kvaser_usb_dev_cfg *cfg,
const struct kvaser_cmd *cmd)
{
u64 ticks;
ktime_t hwtstamp = 0;
if (cmd->header.cmd_no == CMD_EXTENDED) {
struct kvaser_cmd_ext *cmd_ext = (struct kvaser_cmd_ext *)cmd;
ticks = le64_to_cpu(cmd_ext->rx_can.timestamp);
} else {
ticks = le16_to_cpu(cmd->rx_can.timestamp[0]);
ticks += (u64)(le16_to_cpu(cmd->rx_can.timestamp[1])) << 16;
ticks += (u64)(le16_to_cpu(cmd->rx_can.timestamp[2])) << 32;
if (cmd_ext->cmd_no_ext == CMD_RX_MESSAGE_FD)
hwtstamp = kvaser_usb_timestamp64_to_ktime(cfg, cmd_ext->rx_can.timestamp);
else if (cmd_ext->cmd_no_ext == CMD_TX_ACKNOWLEDGE_FD)
hwtstamp = kvaser_usb_timestamp64_to_ktime(cfg, cmd_ext->tx_ack.timestamp);
} else if (cmd->header.cmd_no == CMD_RX_MESSAGE) {
hwtstamp = kvaser_usb_timestamp48_to_ktime(cfg, cmd->rx_can.timestamp);
} else if (cmd->header.cmd_no == CMD_TX_ACKNOWLEDGE) {
hwtstamp = kvaser_usb_timestamp48_to_ktime(cfg, cmd->tx_ack.timestamp);
}
return ns_to_ktime(div_u64(ticks * 1000, cfg->timestamp_freq));
return hwtstamp;
}
static int kvaser_usb_hydra_send_simple_cmd(struct kvaser_usb *dev,
......@@ -1175,6 +1186,7 @@ static void kvaser_usb_hydra_tx_acknowledge(const struct kvaser_usb *dev,
bool one_shot_fail = false;
bool is_err_frame = false;
u16 transid = kvaser_usb_hydra_get_cmd_transid(cmd);
struct sk_buff *skb;
priv = kvaser_usb_hydra_net_priv_from_cmd(dev, cmd);
if (!priv)
......@@ -1201,6 +1213,9 @@ static void kvaser_usb_hydra_tx_acknowledge(const struct kvaser_usb *dev,
spin_lock_irqsave(&priv->tx_contexts_lock, irq_flags);
skb = priv->can.echo_skb[context->echo_index];
if (skb)
skb_hwtstamps(skb)->hwtstamp = kvaser_usb_hydra_ktime_from_cmd(dev->cfg, cmd);
len = can_get_echo_skb(priv->netdev, context->echo_index, NULL);
context->echo_index = dev->max_tx_urbs;
--priv->active_tx_contexts;
......@@ -1234,7 +1249,7 @@ static void kvaser_usb_hydra_rx_msg_std(const struct kvaser_usb *dev,
stats = &priv->netdev->stats;
flags = cmd->rx_can.flags;
hwtstamp = kvaser_usb_hydra_ktime_from_rx_cmd(dev->cfg, cmd);
hwtstamp = kvaser_usb_hydra_ktime_from_cmd(dev->cfg, cmd);
if (flags & KVASER_USB_HYDRA_CF_FLAG_ERROR_FRAME) {
kvaser_usb_hydra_error_frame(priv, &cmd->rx_can.err_frame_data,
......@@ -1302,7 +1317,7 @@ static void kvaser_usb_hydra_rx_msg_ext(const struct kvaser_usb *dev,
KVASER_USB_KCAN_DATA_DLC_SHIFT;
flags = le32_to_cpu(cmd->rx_can.flags);
hwtstamp = kvaser_usb_hydra_ktime_from_rx_cmd(dev->cfg, std_cmd);
hwtstamp = kvaser_usb_hydra_ktime_from_cmd(dev->cfg, std_cmd);
if (flags & KVASER_USB_HYDRA_CF_FLAG_ERROR_FRAME) {
kvaser_usb_hydra_error_frame(priv, &cmd->rx_can.err_frame_data,
......
......@@ -119,6 +119,10 @@
/* Extended CAN identifier flag */
#define KVASER_EXTENDED_FRAME BIT(31)
/* 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;
u8 channel;
......@@ -235,6 +239,20 @@ struct kvaser_cmd_tx_acknowledge_header {
u8 tid;
} __packed;
struct leaf_cmd_tx_acknowledge {
u8 channel;
u8 tid;
__le16 time[3];
u8 padding[2];
} __packed;
struct usbcan_cmd_tx_acknowledge {
u8 channel;
u8 tid;
__le16 time;
u8 padding[2];
} __packed;
struct leaf_cmd_can_error_event {
u8 tid;
u8 flags;
......@@ -281,6 +299,12 @@ struct usbcan_cmd_error_event {
__le16 padding;
} __packed;
struct usbcan_cmd_clk_overflow_event {
u8 tid;
u8 padding;
__le32 time;
} __packed;
struct kvaser_cmd_ctrl_mode {
u8 tid;
u8 channel;
......@@ -347,6 +371,7 @@ struct kvaser_cmd {
struct leaf_cmd_error_event error_event;
struct kvaser_cmd_cap_req cap_req;
struct kvaser_cmd_cap_res cap_res;
struct leaf_cmd_tx_acknowledge tx_ack;
} __packed leaf;
union {
......@@ -355,6 +380,8 @@ struct kvaser_cmd {
struct usbcan_cmd_chip_state_event chip_state_event;
struct usbcan_cmd_can_error_event can_error_event;
struct usbcan_cmd_error_event error_event;
struct usbcan_cmd_tx_acknowledge tx_ack;
struct usbcan_cmd_clk_overflow_event clk_overflow_event;
} __packed usbcan;
struct kvaser_cmd_tx_can tx_can;
......@@ -370,7 +397,7 @@ static const u8 kvaser_usb_leaf_cmd_sizes_leaf[] = {
[CMD_START_CHIP_REPLY] = kvaser_fsize(u.simple),
[CMD_STOP_CHIP_REPLY] = kvaser_fsize(u.simple),
[CMD_GET_CARD_INFO_REPLY] = kvaser_fsize(u.cardinfo),
[CMD_TX_ACKNOWLEDGE] = kvaser_fsize(u.tx_acknowledge_header),
[CMD_TX_ACKNOWLEDGE] = kvaser_fsize(u.leaf.tx_ack),
[CMD_GET_SOFTWARE_INFO_REPLY] = kvaser_fsize(u.leaf.softinfo),
[CMD_RX_STD_MESSAGE] = kvaser_fsize(u.leaf.rx_can),
[CMD_RX_EXT_MESSAGE] = kvaser_fsize(u.leaf.rx_can),
......@@ -388,15 +415,14 @@ static const u8 kvaser_usb_leaf_cmd_sizes_usbcan[] = {
[CMD_START_CHIP_REPLY] = kvaser_fsize(u.simple),
[CMD_STOP_CHIP_REPLY] = kvaser_fsize(u.simple),
[CMD_GET_CARD_INFO_REPLY] = kvaser_fsize(u.cardinfo),
[CMD_TX_ACKNOWLEDGE] = kvaser_fsize(u.tx_acknowledge_header),
[CMD_TX_ACKNOWLEDGE] = kvaser_fsize(u.usbcan.tx_ack),
[CMD_GET_SOFTWARE_INFO_REPLY] = kvaser_fsize(u.usbcan.softinfo),
[CMD_RX_STD_MESSAGE] = kvaser_fsize(u.usbcan.rx_can),
[CMD_RX_EXT_MESSAGE] = kvaser_fsize(u.usbcan.rx_can),
[CMD_CHIP_STATE_EVENT] = kvaser_fsize(u.usbcan.chip_state_event),
[CMD_CAN_ERROR_EVENT] = kvaser_fsize(u.usbcan.can_error_event),
[CMD_ERROR_EVENT] = kvaser_fsize(u.usbcan.error_event),
/* ignored events: */
[CMD_USBCAN_CLOCK_OVERFLOW_EVENT] = CMD_SIZE_ANY,
[CMD_USBCAN_CLOCK_OVERFLOW_EVENT] = kvaser_fsize(u.usbcan.clk_overflow_event),
};
/* Summary of a kvaser error event, for a unified Leaf/Usbcan error
......@@ -463,11 +489,27 @@ static const struct kvaser_usb_dev_cfg kvaser_usb_leaf_usbcan_dev_cfg = {
.bittiming_const = &kvaser_usb_leaf_m16c_bittiming_const,
};
static const struct kvaser_usb_dev_cfg kvaser_usb_leaf_m32c_dev_cfg = {
static const struct kvaser_usb_dev_cfg kvaser_usb_leaf_m32c_dev_cfg_16mhz = {
.clock = {
.freq = 16 * MEGA /* Hz */,
},
.timestamp_freq = 1,
.timestamp_freq = 16,
.bittiming_const = &kvaser_usb_leaf_m32c_bittiming_const,
};
static const struct kvaser_usb_dev_cfg kvaser_usb_leaf_m32c_dev_cfg_24mhz = {
.clock = {
.freq = 16 * MEGA /* Hz */,
},
.timestamp_freq = 24,
.bittiming_const = &kvaser_usb_leaf_m32c_bittiming_const,
};
static const struct kvaser_usb_dev_cfg kvaser_usb_leaf_m32c_dev_cfg_32mhz = {
.clock = {
.freq = 16 * MEGA /* Hz */,
},
.timestamp_freq = 32,
.bittiming_const = &kvaser_usb_leaf_m32c_bittiming_const,
};
......@@ -475,7 +517,7 @@ static const struct kvaser_usb_dev_cfg kvaser_usb_leaf_imx_dev_cfg_16mhz = {
.clock = {
.freq = 16 * MEGA /* Hz */,
},
.timestamp_freq = 1,
.timestamp_freq = 16,
.bittiming_const = &kvaser_usb_flexc_bittiming_const,
};
......@@ -483,7 +525,7 @@ static const struct kvaser_usb_dev_cfg kvaser_usb_leaf_imx_dev_cfg_24mhz = {
.clock = {
.freq = 24 * MEGA /* Hz */,
},
.timestamp_freq = 1,
.timestamp_freq = 24,
.bittiming_const = &kvaser_usb_flexc_bittiming_const,
};
......@@ -491,10 +533,19 @@ static const struct kvaser_usb_dev_cfg kvaser_usb_leaf_imx_dev_cfg_32mhz = {
.clock = {
.freq = 32 * MEGA /* Hz */,
},
.timestamp_freq = 1,
.timestamp_freq = 32,
.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)
{
......@@ -678,8 +729,19 @@ static void kvaser_usb_leaf_get_software_info_leaf(struct kvaser_usb *dev,
if (dev->driver_info->quirks & KVASER_USB_QUIRK_IGNORE_CLK_FREQ) {
/* Firmware expects bittiming parameters calculated for 16MHz
* clock, regardless of the actual clock
* Though, the reported freq is used for timestamps
*/
dev->cfg = &kvaser_usb_leaf_m32c_dev_cfg;
switch (sw_options & KVASER_USB_LEAF_SWOPTION_FREQ_MASK) {
case KVASER_USB_LEAF_SWOPTION_FREQ_16_MHZ_CLK:
dev->cfg = &kvaser_usb_leaf_m32c_dev_cfg_16mhz;
break;
case KVASER_USB_LEAF_SWOPTION_FREQ_24_MHZ_CLK:
dev->cfg = &kvaser_usb_leaf_m32c_dev_cfg_24mhz;
break;
case KVASER_USB_LEAF_SWOPTION_FREQ_32_MHZ_CLK:
dev->cfg = &kvaser_usb_leaf_m32c_dev_cfg_32mhz;
break;
}
} else {
switch (sw_options & KVASER_USB_LEAF_SWOPTION_FREQ_MASK) {
case KVASER_USB_LEAF_SWOPTION_FREQ_16_MHZ_CLK:
......@@ -880,6 +942,8 @@ static void kvaser_usb_leaf_tx_acknowledge(const struct kvaser_usb *dev,
struct kvaser_usb_net_priv *priv;
unsigned long flags;
u8 channel, tid;
struct sk_buff *skb;
ktime_t hwtstamp = 0;
channel = cmd->u.tx_acknowledge_header.channel;
tid = cmd->u.tx_acknowledge_header.tid;
......@@ -901,14 +965,14 @@ static void kvaser_usb_leaf_tx_acknowledge(const struct kvaser_usb *dev,
/* Sometimes the state change doesn't come after a bus-off event */
if (priv->can.restart_ms && priv->can.state == CAN_STATE_BUS_OFF) {
struct sk_buff *skb;
struct sk_buff *err_skb;
struct can_frame *cf;
skb = alloc_can_err_skb(priv->netdev, &cf);
if (skb) {
err_skb = alloc_can_err_skb(priv->netdev, &cf);
if (err_skb) {
cf->can_id |= CAN_ERR_RESTARTED;
netif_rx(skb);
netif_rx(err_skb);
} else {
netdev_err(priv->netdev,
"No memory left for err_skb\n");
......@@ -919,9 +983,20 @@ static void kvaser_usb_leaf_tx_acknowledge(const struct kvaser_usb *dev,
priv->can.state = CAN_STATE_ERROR_ACTIVE;
}
switch (dev->driver_info->family) {
case KVASER_LEAF:
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;
}
spin_lock_irqsave(&priv->tx_contexts_lock, flags);
skb = priv->can.echo_skb[context->echo_index];
if (skb)
skb_hwtstamps(skb)->hwtstamp = hwtstamp;
stats->tx_packets++;
stats->tx_bytes += can_get_echo_skb(priv->netdev,
context->echo_index, NULL);
......@@ -1299,6 +1374,7 @@ static void kvaser_usb_leaf_rx_can_msg(const struct kvaser_usb *dev,
struct net_device_stats *stats;
u8 channel = cmd->u.rx_can_header.channel;
const u8 *rx_data = NULL; /* GCC */
ktime_t hwtstamp = 0;
if (channel >= dev->nchannels) {
dev_err(&dev->intf->dev,
......@@ -1329,9 +1405,11 @@ static void kvaser_usb_leaf_rx_can_msg(const struct kvaser_usb *dev,
switch (dev->driver_info->family) {
case KVASER_LEAF:
rx_data = cmd->u.leaf.rx_can.data;
hwtstamp = kvaser_usb_timestamp48_to_ktime(dev->cfg, cmd->u.leaf.rx_can.time);
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;
}
......@@ -1375,6 +1453,7 @@ static void kvaser_usb_leaf_rx_can_msg(const struct kvaser_usb *dev,
memcpy(cf->data, &rx_data[6], cf->len);
}
skb_hwtstamps(skb)->hwtstamp = hwtstamp;
stats->rx_packets++;
if (!(cf->can_id & CAN_RTR_FLAG))
stats->rx_bytes += cf->len;
......@@ -1508,7 +1587,7 @@ static void kvaser_usb_leaf_get_busparams_reply(const struct kvaser_usb *dev,
complete(&priv->get_busparams_comp);
}
static void kvaser_usb_leaf_handle_command(const struct kvaser_usb *dev,
static void kvaser_usb_leaf_handle_command(struct kvaser_usb *dev,
const struct kvaser_cmd *cmd)
{
if (kvaser_usb_leaf_verify_size(dev, cmd) < 0)
......@@ -1554,12 +1633,15 @@ static void kvaser_usb_leaf_handle_command(const struct kvaser_usb *dev,
kvaser_usb_leaf_get_busparams_reply(dev, cmd);
break;
/* Ignored commands */
case CMD_USBCAN_CLOCK_OVERFLOW_EVENT:
if (dev->driver_info->family != KVASER_USBCAN)
goto warn;
dev->card_data.usbcan_timestamp_msb =
le32_to_cpu(cmd->u.usbcan.clk_overflow_event.time) &
KVASER_USB_USBCAN_CLK_OVERFLOW_MASK;
break;
/* Ignored commands */
case CMD_FLUSH_QUEUE_REPLY:
if (dev->driver_info->family != KVASER_LEAF)
goto warn;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment