diff options
Diffstat (limited to 'drivers/net/can/usb')
-rw-r--r-- | drivers/net/can/usb/Kconfig | 12 | ||||
-rw-r--r-- | drivers/net/can/usb/Makefile | 1 | ||||
-rw-r--r-- | drivers/net/can/usb/esd_usb.c | 352 | ||||
-rw-r--r-- | drivers/net/can/usb/f81604.c | 1201 | ||||
-rw-r--r-- | drivers/net/can/usb/kvaser_usb/kvaser_usb_core.c | 2 | ||||
-rw-r--r-- | drivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c | 13 | ||||
-rw-r--r-- | drivers/net/can/usb/kvaser_usb/kvaser_usb_leaf.c | 6 |
7 files changed, 1401 insertions, 186 deletions
diff --git a/drivers/net/can/usb/Kconfig b/drivers/net/can/usb/Kconfig index 445504ababce..58fcd2b34820 100644 --- a/drivers/net/can/usb/Kconfig +++ b/drivers/net/can/usb/Kconfig @@ -38,6 +38,18 @@ config CAN_ETAS_ES58X To compile this driver as a module, choose M here: the module will be called etas_es58x. +config CAN_F81604 + tristate "Fintek F81604 USB to 2CAN interface" + help + This driver supports the Fintek F81604 USB to 2CAN interface. + The device can support CAN2.0A/B protocol and also support + 2 output pins to control external terminator (optional). + + To compile this driver as a module, choose M here: the module will + be called f81604. + + (see also https://www.fintek.com.tw). + config CAN_GS_USB tristate "Geschwister Schneider UG and candleLight compatible interfaces" help diff --git a/drivers/net/can/usb/Makefile b/drivers/net/can/usb/Makefile index 1ea16be5743b..8b11088e9a59 100644 --- a/drivers/net/can/usb/Makefile +++ b/drivers/net/can/usb/Makefile @@ -7,6 +7,7 @@ obj-$(CONFIG_CAN_8DEV_USB) += usb_8dev.o obj-$(CONFIG_CAN_EMS_USB) += ems_usb.o obj-$(CONFIG_CAN_ESD_USB) += esd_usb.o obj-$(CONFIG_CAN_ETAS_ES58X) += etas_es58x/ +obj-$(CONFIG_CAN_F81604) += f81604.o obj-$(CONFIG_CAN_GS_USB) += gs_usb.o obj-$(CONFIG_CAN_KVASER_USB) += kvaser_usb/ obj-$(CONFIG_CAN_MCBA_USB) += mcba_usb.o diff --git a/drivers/net/can/usb/esd_usb.c b/drivers/net/can/usb/esd_usb.c index d33bac3a6c10..6201637ac0ff 100644 --- a/drivers/net/can/usb/esd_usb.c +++ b/drivers/net/can/usb/esd_usb.c @@ -3,18 +3,19 @@ * CAN driver for esd electronics gmbh CAN-USB/2 and CAN-USB/Micro * * Copyright (C) 2010-2012 esd electronic system design gmbh, Matthias Fuchs <socketcan@esd.eu> - * Copyright (C) 2022 esd electronics gmbh, Frank Jungclaus <frank.jungclaus@esd.eu> + * Copyright (C) 2022-2023 esd electronics gmbh, Frank Jungclaus <frank.jungclaus@esd.eu> */ -#include <linux/ethtool.h> -#include <linux/signal.h> -#include <linux/slab.h> -#include <linux/module.h> -#include <linux/netdevice.h> -#include <linux/usb.h> #include <linux/can.h> #include <linux/can/dev.h> #include <linux/can/error.h> +#include <linux/ethtool.h> +#include <linux/module.h> +#include <linux/netdevice.h> +#include <linux/signal.h> +#include <linux/slab.h> +#include <linux/units.h> +#include <linux/usb.h> MODULE_AUTHOR("Matthias Fuchs <socketcan@esd.eu>"); MODULE_AUTHOR("Frank Jungclaus <frank.jungclaus@esd.eu>"); @@ -22,95 +23,87 @@ MODULE_DESCRIPTION("CAN driver for esd electronics gmbh CAN-USB/2 and CAN-USB/Mi MODULE_LICENSE("GPL v2"); /* USB vendor and product ID */ -#define USB_ESDGMBH_VENDOR_ID 0x0ab4 -#define USB_CANUSB2_PRODUCT_ID 0x0010 -#define USB_CANUSBM_PRODUCT_ID 0x0011 +#define ESD_USB_ESDGMBH_VENDOR_ID 0x0ab4 +#define ESD_USB_CANUSB2_PRODUCT_ID 0x0010 +#define ESD_USB_CANUSBM_PRODUCT_ID 0x0011 /* CAN controller clock frequencies */ -#define ESD_USB2_CAN_CLOCK 60000000 -#define ESD_USBM_CAN_CLOCK 36000000 +#define ESD_USB_2_CAN_CLOCK (60 * MEGA) /* Hz */ +#define ESD_USB_M_CAN_CLOCK (36 * MEGA) /* Hz */ /* Maximum number of CAN nets */ #define ESD_USB_MAX_NETS 2 /* USB commands */ -#define CMD_VERSION 1 /* also used for VERSION_REPLY */ -#define CMD_CAN_RX 2 /* device to host only */ -#define CMD_CAN_TX 3 /* also used for TX_DONE */ -#define CMD_SETBAUD 4 /* also used for SETBAUD_REPLY */ -#define CMD_TS 5 /* also used for TS_REPLY */ -#define CMD_IDADD 6 /* also used for IDADD_REPLY */ +#define ESD_USB_CMD_VERSION 1 /* also used for VERSION_REPLY */ +#define ESD_USB_CMD_CAN_RX 2 /* device to host only */ +#define ESD_USB_CMD_CAN_TX 3 /* also used for TX_DONE */ +#define ESD_USB_CMD_SETBAUD 4 /* also used for SETBAUD_REPLY */ +#define ESD_USB_CMD_TS 5 /* also used for TS_REPLY */ +#define ESD_USB_CMD_IDADD 6 /* also used for IDADD_REPLY */ /* esd CAN message flags - dlc field */ -#define ESD_RTR 0x10 +#define ESD_USB_RTR BIT(4) /* esd CAN message flags - id field */ -#define ESD_EXTID 0x20000000 -#define ESD_EVENT 0x40000000 -#define ESD_IDMASK 0x1fffffff +#define ESD_USB_EXTID BIT(29) +#define ESD_USB_EVENT BIT(30) +#define ESD_USB_IDMASK GENMASK(28, 0) /* esd CAN event ids */ -#define ESD_EV_CAN_ERROR_EXT 2 /* CAN controller specific diagnostic data */ +#define ESD_USB_EV_CAN_ERROR_EXT 2 /* CAN controller specific diagnostic data */ /* baudrate message flags */ -#define ESD_USB_UBR 0x80000000 -#define ESD_USB_LOM 0x40000000 -#define ESD_USB_NO_BAUDRATE 0x7fffffff - -/* bit timing CAN-USB/2 */ -#define ESD_USB2_TSEG1_MIN 1 -#define ESD_USB2_TSEG1_MAX 16 -#define ESD_USB2_TSEG1_SHIFT 16 -#define ESD_USB2_TSEG2_MIN 1 -#define ESD_USB2_TSEG2_MAX 8 -#define ESD_USB2_TSEG2_SHIFT 20 -#define ESD_USB2_SJW_MAX 4 -#define ESD_USB2_SJW_SHIFT 14 -#define ESD_USBM_SJW_SHIFT 24 -#define ESD_USB2_BRP_MIN 1 -#define ESD_USB2_BRP_MAX 1024 -#define ESD_USB2_BRP_INC 1 -#define ESD_USB2_3_SAMPLES 0x00800000 +#define ESD_USB_LOM BIT(30) /* Listen Only Mode */ +#define ESD_USB_UBR BIT(31) /* User Bit Rate (controller BTR) in bits 0..27 */ +#define ESD_USB_NO_BAUDRATE GENMASK(30, 0) /* bit rate unconfigured */ + +/* bit timing esd CAN-USB */ +#define ESD_USB_2_TSEG1_SHIFT 16 +#define ESD_USB_2_TSEG2_SHIFT 20 +#define ESD_USB_2_SJW_SHIFT 14 +#define ESD_USB_M_SJW_SHIFT 24 +#define ESD_USB_TRIPLE_SAMPLES BIT(23) /* esd IDADD message */ -#define ESD_ID_ENABLE 0x80 -#define ESD_MAX_ID_SEGMENT 64 +#define ESD_USB_ID_ENABLE BIT(7) +#define ESD_USB_MAX_ID_SEGMENT 64 /* SJA1000 ECC register (emulated by usb firmware) */ -#define SJA1000_ECC_SEG 0x1F -#define SJA1000_ECC_DIR 0x20 -#define SJA1000_ECC_ERR 0x06 -#define SJA1000_ECC_BIT 0x00 -#define SJA1000_ECC_FORM 0x40 -#define SJA1000_ECC_STUFF 0x80 -#define SJA1000_ECC_MASK 0xc0 +#define ESD_USB_SJA1000_ECC_SEG GENMASK(4, 0) +#define ESD_USB_SJA1000_ECC_DIR BIT(5) +#define ESD_USB_SJA1000_ECC_ERR BIT(2, 1) +#define ESD_USB_SJA1000_ECC_BIT 0x00 +#define ESD_USB_SJA1000_ECC_FORM BIT(6) +#define ESD_USB_SJA1000_ECC_STUFF BIT(7) +#define ESD_USB_SJA1000_ECC_MASK GENMASK(7, 6) /* esd bus state event codes */ -#define ESD_BUSSTATE_MASK 0xc0 -#define ESD_BUSSTATE_WARN 0x40 -#define ESD_BUSSTATE_ERRPASSIVE 0x80 -#define ESD_BUSSTATE_BUSOFF 0xc0 +#define ESD_USB_BUSSTATE_MASK GENMASK(7, 6) +#define ESD_USB_BUSSTATE_WARN BIT(6) +#define ESD_USB_BUSSTATE_ERRPASSIVE BIT(7) +#define ESD_USB_BUSSTATE_BUSOFF GENMASK(7, 6) -#define RX_BUFFER_SIZE 1024 -#define MAX_RX_URBS 4 -#define MAX_TX_URBS 16 /* must be power of 2 */ +#define ESD_USB_RX_BUFFER_SIZE 1024 +#define ESD_USB_MAX_RX_URBS 4 +#define ESD_USB_MAX_TX_URBS 16 /* must be power of 2 */ -struct header_msg { - u8 len; /* len is always the total message length in 32bit words */ +struct esd_usb_header_msg { + u8 len; /* total message length in 32bit words */ u8 cmd; u8 rsvd[2]; }; -struct version_msg { - u8 len; +struct esd_usb_version_msg { + u8 len; /* total message length in 32bit words */ u8 cmd; u8 rsvd; u8 flags; __le32 drv_version; }; -struct version_reply_msg { - u8 len; +struct esd_usb_version_reply_msg { + u8 len; /* total message length in 32bit words */ u8 cmd; u8 nets; u8 features; @@ -120,15 +113,15 @@ struct version_reply_msg { __le32 ts; }; -struct rx_msg { - u8 len; +struct esd_usb_rx_msg { + u8 len; /* total message length in 32bit words */ u8 cmd; u8 net; u8 dlc; __le32 ts; __le32 id; /* upper 3 bits contain flags */ union { - u8 data[8]; + u8 data[CAN_MAX_DLEN]; struct { u8 status; /* CAN Controller Status */ u8 ecc; /* Error Capture Register */ @@ -138,18 +131,18 @@ struct rx_msg { }; }; -struct tx_msg { - u8 len; +struct esd_usb_tx_msg { + u8 len; /* total message length in 32bit words */ u8 cmd; u8 net; u8 dlc; u32 hnd; /* opaque handle, not used by device */ __le32 id; /* upper 3 bits contain flags */ - u8 data[8]; + u8 data[CAN_MAX_DLEN]; }; -struct tx_done_msg { - u8 len; +struct esd_usb_tx_done_msg { + u8 len; /* total message length in 32bit words */ u8 cmd; u8 net; u8 status; @@ -157,16 +150,16 @@ struct tx_done_msg { __le32 ts; }; -struct id_filter_msg { - u8 len; +struct esd_usb_id_filter_msg { + u8 len; /* total message length in 32bit words */ u8 cmd; u8 net; u8 option; - __le32 mask[ESD_MAX_ID_SEGMENT + 1]; + __le32 mask[ESD_USB_MAX_ID_SEGMENT + 1]; /* +1 for 29bit extended IDs */ }; -struct set_baudrate_msg { - u8 len; +struct esd_usb_set_baudrate_msg { + u8 len; /* total message length in 32bit words */ u8 cmd; u8 net; u8 rsvd; @@ -175,19 +168,19 @@ struct set_baudrate_msg { /* Main message type used between library and application */ union __packed esd_usb_msg { - struct header_msg hdr; - struct version_msg version; - struct version_reply_msg version_reply; - struct rx_msg rx; - struct tx_msg tx; - struct tx_done_msg txdone; - struct set_baudrate_msg setbaud; - struct id_filter_msg filter; + struct esd_usb_header_msg hdr; + struct esd_usb_version_msg version; + struct esd_usb_version_reply_msg version_reply; + struct esd_usb_rx_msg rx; + struct esd_usb_tx_msg tx; + struct esd_usb_tx_done_msg txdone; + struct esd_usb_set_baudrate_msg setbaud; + struct esd_usb_id_filter_msg filter; }; static struct usb_device_id esd_usb_table[] = { - {USB_DEVICE(USB_ESDGMBH_VENDOR_ID, USB_CANUSB2_PRODUCT_ID)}, - {USB_DEVICE(USB_ESDGMBH_VENDOR_ID, USB_CANUSBM_PRODUCT_ID)}, + {USB_DEVICE(ESD_USB_ESDGMBH_VENDOR_ID, ESD_USB_CANUSB2_PRODUCT_ID)}, + {USB_DEVICE(ESD_USB_ESDGMBH_VENDOR_ID, ESD_USB_CANUSBM_PRODUCT_ID)}, {} }; MODULE_DEVICE_TABLE(usb, esd_usb_table); @@ -208,8 +201,8 @@ struct esd_usb { int net_count; u32 version; int rxinitdone; - void *rxbuf[MAX_RX_URBS]; - dma_addr_t rxbuf_dma[MAX_RX_URBS]; + void *rxbuf[ESD_USB_MAX_RX_URBS]; + dma_addr_t rxbuf_dma[ESD_USB_MAX_RX_URBS]; }; struct esd_usb_net_priv { @@ -217,7 +210,7 @@ struct esd_usb_net_priv { atomic_t active_tx_jobs; struct usb_anchor tx_submitted; - struct esd_tx_urb_context tx_contexts[MAX_TX_URBS]; + struct esd_tx_urb_context tx_contexts[ESD_USB_MAX_TX_URBS]; struct esd_usb *usb; struct net_device *netdev; @@ -232,9 +225,9 @@ static void esd_usb_rx_event(struct esd_usb_net_priv *priv, struct net_device_stats *stats = &priv->netdev->stats; struct can_frame *cf; struct sk_buff *skb; - u32 id = le32_to_cpu(msg->rx.id) & ESD_IDMASK; + u32 id = le32_to_cpu(msg->rx.id) & ESD_USB_IDMASK; - if (id == ESD_EV_CAN_ERROR_EXT) { + if (id == ESD_USB_EV_CAN_ERROR_EXT) { u8 state = msg->rx.ev_can_err_ext.status; u8 ecc = msg->rx.ev_can_err_ext.ecc; @@ -261,15 +254,15 @@ static void esd_usb_rx_event(struct esd_usb_net_priv *priv, priv->old_state = state; - switch (state & ESD_BUSSTATE_MASK) { - case ESD_BUSSTATE_BUSOFF: + switch (state & ESD_USB_BUSSTATE_MASK) { + case ESD_USB_BUSSTATE_BUSOFF: new_state = CAN_STATE_BUS_OFF; can_bus_off(priv->netdev); break; - case ESD_BUSSTATE_WARN: + case ESD_USB_BUSSTATE_WARN: new_state = CAN_STATE_ERROR_WARNING; break; - case ESD_BUSSTATE_ERRPASSIVE: + case ESD_USB_BUSSTATE_ERRPASSIVE: new_state = CAN_STATE_ERROR_PASSIVE; break; default: @@ -291,14 +284,14 @@ static void esd_usb_rx_event(struct esd_usb_net_priv *priv, cf->can_id |= CAN_ERR_PROT | CAN_ERR_BUSERROR; - switch (ecc & SJA1000_ECC_MASK) { - case SJA1000_ECC_BIT: + switch (ecc & ESD_USB_SJA1000_ECC_MASK) { + case ESD_USB_SJA1000_ECC_BIT: cf->data[2] |= CAN_ERR_PROT_BIT; break; - case SJA1000_ECC_FORM: + case ESD_USB_SJA1000_ECC_FORM: cf->data[2] |= CAN_ERR_PROT_FORM; break; - case SJA1000_ECC_STUFF: + case ESD_USB_SJA1000_ECC_STUFF: cf->data[2] |= CAN_ERR_PROT_STUFF; break; default: @@ -306,11 +299,11 @@ static void esd_usb_rx_event(struct esd_usb_net_priv *priv, } /* Error occurred during transmission? */ - if (!(ecc & SJA1000_ECC_DIR)) + if (!(ecc & ESD_USB_SJA1000_ECC_DIR)) cf->data[2] |= CAN_ERR_PROT_TX; /* Bit stream position in CAN frame as the error was detected */ - cf->data[3] = ecc & SJA1000_ECC_SEG; + cf->data[3] = ecc & ESD_USB_SJA1000_ECC_SEG; } if (skb) { @@ -337,7 +330,7 @@ static void esd_usb_rx_can_msg(struct esd_usb_net_priv *priv, id = le32_to_cpu(msg->rx.id); - if (id & ESD_EVENT) { + if (id & ESD_USB_EVENT) { esd_usb_rx_event(priv, msg); } else { skb = alloc_can_skb(priv->netdev, &cf); @@ -346,14 +339,14 @@ static void esd_usb_rx_can_msg(struct esd_usb_net_priv *priv, return; } - cf->can_id = id & ESD_IDMASK; - can_frame_set_cc_len(cf, msg->rx.dlc & ~ESD_RTR, + cf->can_id = id & ESD_USB_IDMASK; + can_frame_set_cc_len(cf, msg->rx.dlc & ~ESD_USB_RTR, priv->can.ctrlmode); - if (id & ESD_EXTID) + if (id & ESD_USB_EXTID) cf->can_id |= CAN_EFF_FLAG; - if (msg->rx.dlc & ESD_RTR) { + if (msg->rx.dlc & ESD_USB_RTR) { cf->can_id |= CAN_RTR_FLAG; } else { for (i = 0; i < cf->len; i++) @@ -377,7 +370,7 @@ static void esd_usb_tx_done_msg(struct esd_usb_net_priv *priv, if (!netif_device_present(netdev)) return; - context = &priv->tx_contexts[msg->txdone.hnd & (MAX_TX_URBS - 1)]; + context = &priv->tx_contexts[msg->txdone.hnd & (ESD_USB_MAX_TX_URBS - 1)]; if (!msg->txdone.status) { stats->tx_packets++; @@ -389,7 +382,7 @@ static void esd_usb_tx_done_msg(struct esd_usb_net_priv *priv, } /* Release context */ - context->echo_index = MAX_TX_URBS; + context->echo_index = ESD_USB_MAX_TX_URBS; atomic_dec(&priv->active_tx_jobs); netif_wake_queue(netdev); @@ -424,7 +417,7 @@ static void esd_usb_read_bulk_callback(struct urb *urb) msg = (union esd_usb_msg *)(urb->transfer_buffer + pos); switch (msg->hdr.cmd) { - case CMD_CAN_RX: + case ESD_USB_CMD_CAN_RX: if (msg->rx.net >= dev->net_count) { dev_err(dev->udev->dev.parent, "format error\n"); break; @@ -433,7 +426,7 @@ static void esd_usb_read_bulk_callback(struct urb *urb) esd_usb_rx_can_msg(dev->nets[msg->rx.net], msg); break; - case CMD_CAN_TX: + case ESD_USB_CMD_CAN_TX: if (msg->txdone.net >= dev->net_count) { dev_err(dev->udev->dev.parent, "format error\n"); break; @@ -444,7 +437,7 @@ static void esd_usb_read_bulk_callback(struct urb *urb) break; } - pos += msg->hdr.len << 2; + pos += msg->hdr.len * sizeof(u32); /* convert to # of bytes */ if (pos > urb->actual_length) { dev_err(dev->udev->dev.parent, "format error\n"); @@ -454,7 +447,7 @@ static void esd_usb_read_bulk_callback(struct urb *urb) resubmit_urb: usb_fill_bulk_urb(urb, dev->udev, usb_rcvbulkpipe(dev->udev, 1), - urb->transfer_buffer, RX_BUFFER_SIZE, + urb->transfer_buffer, ESD_USB_RX_BUFFER_SIZE, esd_usb_read_bulk_callback, dev); retval = usb_submit_urb(urb, GFP_ATOMIC); @@ -538,7 +531,7 @@ static int esd_usb_send_msg(struct esd_usb *dev, union esd_usb_msg *msg) return usb_bulk_msg(dev->udev, usb_sndbulkpipe(dev->udev, 2), msg, - msg->hdr.len << 2, + msg->hdr.len * sizeof(u32), /* convert to # of bytes */ &actual_length, 1000); } @@ -563,7 +556,7 @@ static int esd_usb_setup_rx_urbs(struct esd_usb *dev) if (dev->rxinitdone) return 0; - for (i = 0; i < MAX_RX_URBS; i++) { + for (i = 0; i < ESD_USB_MAX_RX_URBS; i++) { struct urb *urb = NULL; u8 *buf = NULL; dma_addr_t buf_dma; @@ -575,7 +568,7 @@ static int esd_usb_setup_rx_urbs(struct esd_usb *dev) break; } - buf = usb_alloc_coherent(dev->udev, RX_BUFFER_SIZE, GFP_KERNEL, + buf = usb_alloc_coherent(dev->udev, ESD_USB_RX_BUFFER_SIZE, GFP_KERNEL, &buf_dma); if (!buf) { dev_warn(dev->udev->dev.parent, @@ -588,7 +581,7 @@ static int esd_usb_setup_rx_urbs(struct esd_usb *dev) usb_fill_bulk_urb(urb, dev->udev, usb_rcvbulkpipe(dev->udev, 1), - buf, RX_BUFFER_SIZE, + buf, ESD_USB_RX_BUFFER_SIZE, esd_usb_read_bulk_callback, dev); urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; usb_anchor_urb(urb, &dev->rx_submitted); @@ -596,7 +589,7 @@ static int esd_usb_setup_rx_urbs(struct esd_usb *dev) err = usb_submit_urb(urb, GFP_KERNEL); if (err) { usb_unanchor_urb(urb); - usb_free_coherent(dev->udev, RX_BUFFER_SIZE, buf, + usb_free_coherent(dev->udev, ESD_USB_RX_BUFFER_SIZE, buf, urb->transfer_dma); goto freeurb; } @@ -618,7 +611,7 @@ freeurb: } /* Warn if we've couldn't transmit all the URBs */ - if (i < MAX_RX_URBS) { + if (i < ESD_USB_MAX_RX_URBS) { dev_warn(dev->udev->dev.parent, "rx performance may be slow\n"); } @@ -653,14 +646,14 @@ static int esd_usb_start(struct esd_usb_net_priv *priv) * the number of the starting bitmask (0..64) to the filter.option * field followed by only some bitmasks. */ - msg->hdr.cmd = CMD_IDADD; - msg->hdr.len = 2 + ESD_MAX_ID_SEGMENT; + msg->hdr.cmd = ESD_USB_CMD_IDADD; + msg->hdr.len = sizeof(struct esd_usb_id_filter_msg) / sizeof(u32); /* # of 32bit words */ msg->filter.net = priv->index; - msg->filter.option = ESD_ID_ENABLE; /* start with segment 0 */ - for (i = 0; i < ESD_MAX_ID_SEGMENT; i++) - msg->filter.mask[i] = cpu_to_le32(0xffffffff); + msg->filter.option = ESD_USB_ID_ENABLE; /* start with segment 0 */ + for (i = 0; i < ESD_USB_MAX_ID_SEGMENT; i++) + msg->filter.mask[i] = cpu_to_le32(GENMASK(31, 0)); /* enable 29bit extended IDs */ - msg->filter.mask[ESD_MAX_ID_SEGMENT] = cpu_to_le32(0x00000001); + msg->filter.mask[ESD_USB_MAX_ID_SEGMENT] = cpu_to_le32(BIT(0)); err = esd_usb_send_msg(dev, msg); if (err) @@ -689,8 +682,8 @@ static void unlink_all_urbs(struct esd_usb *dev) usb_kill_anchored_urbs(&dev->rx_submitted); - for (i = 0; i < MAX_RX_URBS; ++i) - usb_free_coherent(dev->udev, RX_BUFFER_SIZE, + for (i = 0; i < ESD_USB_MAX_RX_URBS; ++i) + usb_free_coherent(dev->udev, ESD_USB_RX_BUFFER_SIZE, dev->rxbuf[i], dev->rxbuf_dma[i]); for (i = 0; i < dev->net_count; i++) { @@ -699,8 +692,8 @@ static void unlink_all_urbs(struct esd_usb *dev) usb_kill_anchored_urbs(&priv->tx_submitted); atomic_set(&priv->active_tx_jobs, 0); - for (j = 0; j < MAX_TX_URBS; j++) - priv->tx_contexts[j].echo_index = MAX_TX_URBS; + for (j = 0; j < ESD_USB_MAX_TX_URBS; j++) + priv->tx_contexts[j].echo_index = ESD_USB_MAX_TX_URBS; } } } @@ -765,25 +758,27 @@ static netdev_tx_t esd_usb_start_xmit(struct sk_buff *skb, msg = (union esd_usb_msg *)buf; - msg->hdr.len = 3; /* minimal length */ - msg->hdr.cmd = CMD_CAN_TX; + /* minimal length as # of 32bit words */ + msg->hdr.len = offsetof(struct esd_usb_tx_msg, data) / sizeof(u32); + msg->hdr.cmd = ESD_USB_CMD_CAN_TX; msg->tx.net = priv->index; msg->tx.dlc = can_get_cc_dlc(cf, priv->can.ctrlmode); msg->tx.id = cpu_to_le32(cf->can_id & CAN_ERR_MASK); if (cf->can_id & CAN_RTR_FLAG) - msg->tx.dlc |= ESD_RTR; + msg->tx.dlc |= ESD_USB_RTR; if (cf->can_id & CAN_EFF_FLAG) - msg->tx.id |= cpu_to_le32(ESD_EXTID); + msg->tx.id |= cpu_to_le32(ESD_USB_EXTID); for (i = 0; i < cf->len; i++) msg->tx.data[i] = cf->data[i]; - msg->hdr.len += (cf->len + 3) >> 2; + /* round up, then divide by 4 to add the payload length as # of 32bit words */ + msg->hdr.len += DIV_ROUND_UP(cf->len, sizeof(u32)); - for (i = 0; i < MAX_TX_URBS; i++) { - if (priv->tx_contexts[i].echo_index == MAX_TX_URBS) { + for (i = 0; i < ESD_USB_MAX_TX_URBS; i++) { + if (priv->tx_contexts[i].echo_index == ESD_USB_MAX_TX_URBS) { context = &priv->tx_contexts[i]; break; } @@ -800,10 +795,10 @@ static netdev_tx_t esd_usb_start_xmit(struct sk_buff *skb, context->echo_index = i; /* hnd must not be 0 - MSB is stripped in txdone handling */ - msg->tx.hnd = 0x80000000 | i; /* returned in TX done message */ + msg->tx.hnd = BIT(31) | i; /* returned in TX done message */ usb_fill_bulk_urb(urb, dev->udev, usb_sndbulkpipe(dev->udev, 2), buf, - msg->hdr.len << 2, + msg->hdr.len * sizeof(u32), /* convert to # of bytes */ esd_usb_write_bulk_callback, context); urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; @@ -815,7 +810,7 @@ static netdev_tx_t esd_usb_start_xmit(struct sk_buff *skb, atomic_inc(&priv->active_tx_jobs); /* Slow down tx path */ - if (atomic_read(&priv->active_tx_jobs) >= MAX_TX_URBS) + if (atomic_read(&priv->active_tx_jobs) >= ESD_USB_MAX_TX_URBS) netif_stop_queue(netdev); err = usb_submit_urb(urb, GFP_ATOMIC); @@ -865,18 +860,18 @@ static int esd_usb_close(struct net_device *netdev) return -ENOMEM; /* Disable all IDs (see esd_usb_start()) */ - msg->hdr.cmd = CMD_IDADD; - msg->hdr.len = 2 + ESD_MAX_ID_SEGMENT; + msg->hdr.cmd = ESD_USB_CMD_IDADD; + msg->hdr.len = sizeof(struct esd_usb_id_filter_msg) / sizeof(u32);/* # of 32bit words */ msg->filter.net = priv->index; - msg->filter.option = ESD_ID_ENABLE; /* start with segment 0 */ - for (i = 0; i <= ESD_MAX_ID_SEGMENT; i++) + msg->filter.option = ESD_USB_ID_ENABLE; /* start with segment 0 */ + for (i = 0; i <= ESD_USB_MAX_ID_SEGMENT; i++) msg->filter.mask[i] = 0; if (esd_usb_send_msg(priv->usb, msg) < 0) netdev_err(netdev, "sending idadd message failed\n"); /* set CAN controller to reset mode */ - msg->hdr.len = 2; - msg->hdr.cmd = CMD_SETBAUD; + msg->hdr.len = sizeof(struct esd_usb_set_baudrate_msg) / sizeof(u32); /* # of 32bit words */ + msg->hdr.cmd = ESD_USB_CMD_SETBAUD; msg->setbaud.net = priv->index; msg->setbaud.rsvd = 0; msg->setbaud.baud = cpu_to_le32(ESD_USB_NO_BAUDRATE); @@ -905,20 +900,21 @@ static const struct ethtool_ops esd_usb_ethtool_ops = { .get_ts_info = ethtool_op_get_ts_info, }; -static const struct can_bittiming_const esd_usb2_bittiming_const = { - .name = "esd_usb2", - .tseg1_min = ESD_USB2_TSEG1_MIN, - .tseg1_max = ESD_USB2_TSEG1_MAX, - .tseg2_min = ESD_USB2_TSEG2_MIN, - .tseg2_max = ESD_USB2_TSEG2_MAX, - .sjw_max = ESD_USB2_SJW_MAX, - .brp_min = ESD_USB2_BRP_MIN, - .brp_max = ESD_USB2_BRP_MAX, - .brp_inc = ESD_USB2_BRP_INC, +static const struct can_bittiming_const esd_usb_2_bittiming_const = { + .name = "esd_usb_2", + .tseg1_min = 1, + .tseg1_max = 16, + .tseg2_min = 1, + .tseg2_max = 8, + .sjw_max = 4, + .brp_min = 1, + .brp_max = 1024, + .brp_inc = 1, }; -static int esd_usb2_set_bittiming(struct net_device *netdev) +static int esd_usb_2_set_bittiming(struct net_device *netdev) { + const struct can_bittiming_const *btc = &esd_usb_2_bittiming_const; struct esd_usb_net_priv *priv = netdev_priv(netdev); struct can_bittiming *bt = &priv->can.bittiming; union esd_usb_msg *msg; @@ -930,35 +926,35 @@ static int esd_usb2_set_bittiming(struct net_device *netdev) if (priv->can.ctrlmode & CAN_CTRLMODE_LISTENONLY) canbtr |= ESD_USB_LOM; - canbtr |= (bt->brp - 1) & (ESD_USB2_BRP_MAX - 1); + canbtr |= (bt->brp - 1) & (btc->brp_max - 1); if (le16_to_cpu(priv->usb->udev->descriptor.idProduct) == - USB_CANUSBM_PRODUCT_ID) - sjw_shift = ESD_USBM_SJW_SHIFT; + ESD_USB_CANUSBM_PRODUCT_ID) + sjw_shift = ESD_USB_M_SJW_SHIFT; else - sjw_shift = ESD_USB2_SJW_SHIFT; + sjw_shift = ESD_USB_2_SJW_SHIFT; - canbtr |= ((bt->sjw - 1) & (ESD_USB2_SJW_MAX - 1)) + canbtr |= ((bt->sjw - 1) & (btc->sjw_max - 1)) << sjw_shift; canbtr |= ((bt->prop_seg + bt->phase_seg1 - 1) - & (ESD_USB2_TSEG1_MAX - 1)) - << ESD_USB2_TSEG1_SHIFT; - canbtr |= ((bt->phase_seg2 - 1) & (ESD_USB2_TSEG2_MAX - 1)) - << ESD_USB2_TSEG2_SHIFT; + & (btc->tseg1_max - 1)) + << ESD_USB_2_TSEG1_SHIFT; + canbtr |= ((bt->phase_seg2 - 1) & (btc->tseg2_max - 1)) + << ESD_USB_2_TSEG2_SHIFT; if (priv->can.ctrlmode & CAN_CTRLMODE_3_SAMPLES) - canbtr |= ESD_USB2_3_SAMPLES; + canbtr |= ESD_USB_TRIPLE_SAMPLES; msg = kmalloc(sizeof(*msg), GFP_KERNEL); if (!msg) return -ENOMEM; - msg->hdr.len = 2; - msg->hdr.cmd = CMD_SETBAUD; + msg->hdr.len = sizeof(struct esd_usb_set_baudrate_msg) / sizeof(u32); /* # of 32bit words */ + msg->hdr.cmd = ESD_USB_CMD_SETBAUD; msg->setbaud.net = priv->index; msg->setbaud.rsvd = 0; msg->setbaud.baud = cpu_to_le32(canbtr); - netdev_info(netdev, "setting BTR=%#x\n", canbtr); + netdev_dbg(netdev, "setting BTR=%#x\n", canbtr); err = esd_usb_send_msg(priv->usb, msg); @@ -999,7 +995,7 @@ static int esd_usb_probe_one_net(struct usb_interface *intf, int index) int err = 0; int i; - netdev = alloc_candev(sizeof(*priv), MAX_TX_URBS); + netdev = alloc_candev(sizeof(*priv), ESD_USB_MAX_TX_URBS); if (!netdev) { dev_err(&intf->dev, "couldn't alloc candev\n"); err = -ENOMEM; @@ -1011,8 +1007,8 @@ static int esd_usb_probe_one_net(struct usb_interface *intf, int index) init_usb_anchor(&priv->tx_submitted); atomic_set(&priv->active_tx_jobs, 0); - for (i = 0; i < MAX_TX_URBS; i++) - priv->tx_contexts[i].echo_index = MAX_TX_URBS; + for (i = 0; i < ESD_USB_MAX_TX_URBS; i++) + priv->tx_contexts[i].echo_index = ESD_USB_MAX_TX_URBS; priv->usb = dev; priv->netdev = netdev; @@ -1024,15 +1020,15 @@ static int esd_usb_probe_one_net(struct usb_interface *intf, int index) CAN_CTRLMODE_BERR_REPORTING; if (le16_to_cpu(dev->udev->descriptor.idProduct) == - USB_CANUSBM_PRODUCT_ID) - priv->can.clock.freq = ESD_USBM_CAN_CLOCK; + ESD_USB_CANUSBM_PRODUCT_ID) + priv->can.clock.freq = ESD_USB_M_CAN_CLOCK; else { - priv->can.clock.freq = ESD_USB2_CAN_CLOCK; + priv->can.clock.freq = ESD_USB_2_CAN_CLOCK; priv->can.ctrlmode_supported |= CAN_CTRLMODE_3_SAMPLES; } - priv->can.bittiming_const = &esd_usb2_bittiming_const; - priv->can.do_set_bittiming = esd_usb2_set_bittiming; + priv->can.bittiming_const = &esd_usb_2_bittiming_const; + priv->can.do_set_bittiming = esd_usb_2_set_bittiming; priv->can.do_set_mode = esd_usb_set_mode; priv->can.do_get_berr_counter = esd_usb_get_berr_counter; @@ -1090,8 +1086,8 @@ static int esd_usb_probe(struct usb_interface *intf, } /* query number of CAN interfaces (nets) */ - msg->hdr.cmd = CMD_VERSION; - msg->hdr.len = 2; + msg->hdr.cmd = ESD_USB_CMD_VERSION; + msg->hdr.len = sizeof(struct esd_usb_version_msg) / sizeof(u32); /* # of 32bit words */ msg->version.rsvd = 0; msg->version.flags = 0; msg->version.drv_version = 0; diff --git a/drivers/net/can/usb/f81604.c b/drivers/net/can/usb/f81604.c new file mode 100644 index 000000000000..ec8cef7fd2d5 --- /dev/null +++ b/drivers/net/can/usb/f81604.c @@ -0,0 +1,1201 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Fintek F81604 USB-to-2CAN controller driver. + * + * Copyright (C) 2023 Ji-Ze Hong (Peter Hong) <peter_hong@fintek.com.tw> + */ +#include <linux/bitfield.h> +#include <linux/netdevice.h> +#include <linux/units.h> +#include <linux/usb.h> + +#include <linux/can.h> +#include <linux/can/dev.h> +#include <linux/can/error.h> +#include <linux/can/platform/sja1000.h> + +#include <asm-generic/unaligned.h> + +/* vendor and product id */ +#define F81604_VENDOR_ID 0x2c42 +#define F81604_PRODUCT_ID 0x1709 +#define F81604_CAN_CLOCK (12 * MEGA) +#define F81604_MAX_DEV 2 +#define F81604_SET_DEVICE_RETRY 10 + +#define F81604_USB_TIMEOUT 2000 +#define F81604_SET_GET_REGISTER 0xA0 +#define F81604_PORT_OFFSET 0x1000 +#define F81604_MAX_RX_URBS 4 + +#define F81604_CMD_DATA 0x00 + +#define F81604_DLC_LEN_MASK GENMASK(3, 0) +#define F81604_DLC_EFF_BIT BIT(7) +#define F81604_DLC_RTR_BIT BIT(6) + +#define F81604_SFF_SHIFT 5 +#define F81604_EFF_SHIFT 3 + +#define F81604_BRP_MASK GENMASK(5, 0) +#define F81604_SJW_MASK GENMASK(7, 6) + +#define F81604_SEG1_MASK GENMASK(3, 0) +#define F81604_SEG2_MASK GENMASK(6, 4) + +#define F81604_CLEAR_ALC 0 +#define F81604_CLEAR_ECC 1 +#define F81604_CLEAR_OVERRUN 2 + +/* device setting */ +#define F81604_CTRL_MODE_REG 0x80 +#define F81604_TX_ONESHOT (0x03 << 3) +#define F81604_TX_NORMAL (0x01 << 3) +#define F81604_RX_AUTO_RELEASE_BUF BIT(1) +#define F81604_INT_WHEN_CHANGE BIT(0) + +#define F81604_TERMINATOR_REG 0x105 +#define F81604_CAN0_TERM BIT(2) +#define F81604_CAN1_TERM BIT(3) + +#define F81604_TERMINATION_DISABLED CAN_TERMINATION_DISABLED +#define F81604_TERMINATION_ENABLED 120 + +/* SJA1000 registers - manual section 6.4 (Pelican Mode) */ +#define F81604_SJA1000_MOD 0x00 +#define F81604_SJA1000_CMR 0x01 +#define F81604_SJA1000_IR 0x03 +#define F81604_SJA1000_IER 0x04 +#define F81604_SJA1000_ALC 0x0B +#define F81604_SJA1000_ECC 0x0C +#define F81604_SJA1000_RXERR 0x0E +#define F81604_SJA1000_TXERR 0x0F +#define F81604_SJA1000_ACCC0 0x10 +#define F81604_SJA1000_ACCM0 0x14 +#define F81604_MAX_FILTER_CNT 4 + +/* Common registers - manual section 6.5 */ +#define F81604_SJA1000_BTR0 0x06 +#define F81604_SJA1000_BTR1 0x07 +#define F81604_SJA1000_BTR1_SAMPLE_TRIPLE BIT(7) +#define F81604_SJA1000_OCR 0x08 +#define F81604_SJA1000_CDR 0x1F + +/* mode register */ +#define F81604_SJA1000_MOD_RM 0x01 +#define F81604_SJA1000_MOD_LOM 0x02 +#define F81604_SJA1000_MOD_STM 0x04 + +/* commands */ +#define F81604_SJA1000_CMD_CDO 0x08 + +/* interrupt sources */ +#define F81604_SJA1000_IRQ_BEI 0x80 +#define F81604_SJA1000_IRQ_ALI 0x40 +#define F81604_SJA1000_IRQ_EPI 0x20 +#define F81604_SJA1000_IRQ_DOI 0x08 +#define F81604_SJA1000_IRQ_EI 0x04 +#define F81604_SJA1000_IRQ_TI 0x02 +#define F81604_SJA1000_IRQ_RI 0x01 +#define F81604_SJA1000_IRQ_ALL 0xFF +#define F81604_SJA1000_IRQ_OFF 0x00 + +/* status register content */ +#define F81604_SJA1000_SR_BS 0x80 +#define F81604_SJA1000_SR_ES 0x40 +#define F81604_SJA1000_SR_TCS 0x08 + +/* ECC register */ +#define F81604_SJA1000_ECC_SEG 0x1F +#define F81604_SJA1000_ECC_DIR 0x20 +#define F81604_SJA1000_ECC_BIT 0x00 +#define F81604_SJA1000_ECC_FORM 0x40 +#define F81604_SJA1000_ECC_STUFF 0x80 +#define F81604_SJA1000_ECC_MASK 0xc0 + +/* ALC register */ +#define F81604_SJA1000_ALC_MASK 0x1f + +/* table of devices that work with this driver */ +static const struct usb_device_id f81604_table[] = { + { USB_DEVICE(F81604_VENDOR_ID, F81604_PRODUCT_ID) }, + {} /* Terminating entry */ +}; + +MODULE_DEVICE_TABLE(usb, f81604_table); + +static const struct ethtool_ops f81604_ethtool_ops = { + .get_ts_info = ethtool_op_get_ts_info, +}; + +static const u16 f81604_termination[] = { F81604_TERMINATION_DISABLED, + F81604_TERMINATION_ENABLED }; + +struct f81604_priv { + struct net_device *netdev[F81604_MAX_DEV]; +}; + +struct f81604_port_priv { + struct can_priv can; + struct net_device *netdev; + struct sk_buff *echo_skb; + + unsigned long clear_flags; + struct work_struct clear_reg_work; + + struct usb_device *dev; + struct usb_interface *intf; + + struct usb_anchor urbs_anchor; +}; + +/* Interrupt endpoint data format: + * Byte 0: Status register. + * Byte 1: Interrupt register. + * Byte 2: Interrupt enable register. + * Byte 3: Arbitration lost capture(ALC) register. + * Byte 4: Error code capture(ECC) register. + * Byte 5: Error warning limit register. + * Byte 6: RX error counter register. + * Byte 7: TX error counter register. + * Byte 8: Reserved. + */ +struct f81604_int_data { + u8 sr; + u8 isrc; + u8 ier; + u8 alc; + u8 ecc; + u8 ewlr; + u8 rxerr; + u8 txerr; + u8 val; +} __packed __aligned(4); + +struct f81604_sff { + __be16 id; + u8 data[CAN_MAX_DLEN]; +} __packed __aligned(2); + +struct f81604_eff { + __be32 id; + u8 data[CAN_MAX_DLEN]; +} __packed __aligned(2); + +struct f81604_can_frame { + u8 cmd; + + /* According for F81604 DLC define: + * bit 3~0: data length (0~8) + * bit6: is RTR flag. + * bit7: is EFF frame. + */ + u8 dlc; + + union { + struct f81604_sff sff; + struct f81604_eff eff; + }; +} __packed __aligned(2); + +static const u8 bulk_in_addr[F81604_MAX_DEV] = { 2, 4 }; +static const u8 bulk_out_addr[F81604_MAX_DEV] = { 1, 3 }; +static const u8 int_in_addr[F81604_MAX_DEV] = { 1, 3 }; + +static int f81604_write(struct usb_device *dev, u16 reg, u8 data) +{ + int ret; + + ret = usb_control_msg_send(dev, 0, F81604_SET_GET_REGISTER, + USB_TYPE_VENDOR | USB_DIR_OUT, 0, reg, + &data, sizeof(data), F81604_USB_TIMEOUT, + GFP_KERNEL); + if (ret) + dev_err(&dev->dev, "%s: reg: %x data: %x failed: %pe\n", + __func__, reg, data, ERR_PTR(ret)); + + return ret; +} + +static int f81604_read(struct usb_device *dev, u16 reg, u8 *data) +{ + int ret; + + ret = usb_control_msg_recv(dev, 0, F81604_SET_GET_REGISTER, + USB_TYPE_VENDOR | USB_DIR_IN, 0, reg, data, + sizeof(*data), F81604_USB_TIMEOUT, + GFP_KERNEL); + + if (ret < 0) + dev_err(&dev->dev, "%s: reg: %x failed: %pe\n", __func__, reg, + ERR_PTR(ret)); + + return ret; +} + +static int f81604_update_bits(struct usb_device *dev, u16 reg, u8 mask, + u8 data) +{ + int ret; + u8 tmp; + + ret = f81604_read(dev, reg, &tmp); + if (ret) + return ret; + + tmp &= ~mask; + tmp |= (mask & data); + + return f81604_write(dev, reg, tmp); +} + +static int f81604_sja1000_write(struct f81604_port_priv *priv, u16 reg, + u8 data) +{ + int port = priv->netdev->dev_port; + int real_reg; + + real_reg = reg + F81604_PORT_OFFSET * port + F81604_PORT_OFFSET; + return f81604_write(priv->dev, real_reg, data); +} + +static int f81604_sja1000_read(struct f81604_port_priv *priv, u16 reg, + u8 *data) +{ + int port = priv->netdev->dev_port; + int real_reg; + + real_reg = reg + F81604_PORT_OFFSET * port + F81604_PORT_OFFSET; + return f81604_read(priv->dev, real_reg, data); +} + +static int f81604_set_reset_mode(struct f81604_port_priv *priv) +{ + int ret, i; + u8 tmp; + + /* disable interrupts */ + ret = f81604_sja1000_write(priv, F81604_SJA1000_IER, + F81604_SJA1000_IRQ_OFF); + if (ret) + return ret; + + for (i = 0; i < F81604_SET_DEVICE_RETRY; i++) { + ret = f81604_sja1000_read(priv, F81604_SJA1000_MOD, &tmp); + if (ret) + return ret; + + /* check reset bit */ + if (tmp & F81604_SJA1000_MOD_RM) { + priv->can.state = CAN_STATE_STOPPED; + return 0; + } + + /* reset chip */ + ret = f81604_sja1000_write(priv, F81604_SJA1000_MOD, + F81604_SJA1000_MOD_RM); + if (ret) + return ret; + } + + return -EPERM; +} + +static int f81604_set_normal_mode(struct f81604_port_priv *priv) +{ + u8 tmp, ier = 0; + u8 mod_reg = 0; + int ret, i; + + for (i = 0; i < F81604_SET_DEVICE_RETRY; i++) { + ret = f81604_sja1000_read(priv, F81604_SJA1000_MOD, &tmp); + if (ret) + return ret; + + /* check reset bit */ + if ((tmp & F81604_SJA1000_MOD_RM) == 0) { + priv->can.state = CAN_STATE_ERROR_ACTIVE; + /* enable interrupts, RI handled by bulk-in */ + ier = F81604_SJA1000_IRQ_ALL & ~F81604_SJA1000_IRQ_RI; + if (!(priv->can.ctrlmode & + CAN_CTRLMODE_BERR_REPORTING)) + ier &= ~F81604_SJA1000_IRQ_BEI; + + return f81604_sja1000_write(priv, F81604_SJA1000_IER, + ier); + } + + /* set chip to normal mode */ + if (priv->can.ctrlmode & CAN_CTRLMODE_LISTENONLY) + mod_reg |= F81604_SJA1000_MOD_LOM; + if (priv->can.ctrlmode & CAN_CTRLMODE_PRESUME_ACK) + mod_reg |= F81604_SJA1000_MOD_STM; + + ret = f81604_sja1000_write(priv, F81604_SJA1000_MOD, mod_reg); + if (ret) + return ret; + } + + return -EPERM; +} + +static int f81604_chipset_init(struct f81604_port_priv *priv) +{ + int i, ret; + + /* set clock divider and output control register */ + ret = f81604_sja1000_write(priv, F81604_SJA1000_CDR, + CDR_CBP | CDR_PELICAN); + if (ret) + return ret; + + /* set acceptance filter (accept all) */ + for (i = 0; i < F81604_MAX_FILTER_CNT; ++i) { + ret = f81604_sja1000_write(priv, F81604_SJA1000_ACCC0 + i, 0); + if (ret) + return ret; + } + + for (i = 0; i < F81604_MAX_FILTER_CNT; ++i) { + ret = f81604_sja1000_write(priv, F81604_SJA1000_ACCM0 + i, + 0xFF); + if (ret) + return ret; + } + + return f81604_sja1000_write(priv, F81604_SJA1000_OCR, + OCR_TX0_PUSHPULL | OCR_TX1_PUSHPULL | + OCR_MODE_NORMAL); +} + +static void f81604_process_rx_packet(struct net_device *netdev, + struct f81604_can_frame *frame) +{ + struct net_device_stats *stats = &netdev->stats; + struct can_frame *cf; + struct sk_buff *skb; + + if (frame->cmd != F81604_CMD_DATA) + return; + + skb = alloc_can_skb(netdev, &cf); + if (!skb) { + stats->rx_dropped++; + return; + } + + cf->len = can_cc_dlc2len(frame->dlc & F81604_DLC_LEN_MASK); + + if (frame->dlc & F81604_DLC_EFF_BIT) { + cf->can_id = get_unaligned_be32(&frame->eff.id) >> + F81604_EFF_SHIFT; + cf->can_id |= CAN_EFF_FLAG; + + if (!(frame->dlc & F81604_DLC_RTR_BIT)) + memcpy(cf->data, frame->eff.data, cf->len); + } else { + cf->can_id = get_unaligned_be16(&frame->sff.id) >> + F81604_SFF_SHIFT; + + if (!(frame->dlc & F81604_DLC_RTR_BIT)) + memcpy(cf->data, frame->sff.data, cf->len); + } + + if (frame->dlc & F81604_DLC_RTR_BIT) + cf->can_id |= CAN_RTR_FLAG; + else + stats->rx_bytes += cf->len; + + stats->rx_packets++; + netif_rx(skb); +} + +static void f81604_read_bulk_callback(struct urb *urb) +{ + struct f81604_can_frame *frame = urb->transfer_buffer; + struct net_device *netdev = urb->context; + int ret; + + if (!netif_device_present(netdev)) + return; + + if (urb->status) + netdev_info(netdev, "%s: URB aborted %pe\n", __func__, + ERR_PTR(urb->status)); + + switch (urb->status) { + case 0: /* success */ + break; + + case -ENOENT: + case -EPIPE: + case -EPROTO: + case -ESHUTDOWN: + return; + + default: + goto resubmit_urb; + } + + if (urb->actual_length != sizeof(*frame)) { + netdev_warn(netdev, "URB length %u not equal to %zu\n", + urb->actual_length, sizeof(*frame)); + goto resubmit_urb; + } + + f81604_process_rx_packet(netdev, frame); + +resubmit_urb: + ret = usb_submit_urb(urb, GFP_ATOMIC); + if (ret == -ENODEV) + netif_device_detach(netdev); + else if (ret) + netdev_err(netdev, + "%s: failed to resubmit read bulk urb: %pe\n", + __func__, ERR_PTR(ret)); +} + +static void f81604_handle_tx(struct f81604_port_priv *priv, + struct f81604_int_data *data) +{ + struct net_device *netdev = priv->netdev; + struct net_device_stats *stats = &netdev->stats; + + /* transmission buffer released */ + if (priv->can.ctrlmode & CAN_CTRLMODE_ONE_SHOT && + !(data->sr & F81604_SJA1000_SR_TCS)) { + stats->tx_errors++; + can_free_echo_skb(netdev, 0, NULL); + } else { + /* transmission complete */ + stats->tx_bytes += can_get_echo_skb(netdev, 0, NULL); + stats->tx_packets++; + } + + netif_wake_queue(netdev); +} + +static void f81604_handle_can_bus_errors(struct f81604_port_priv *priv, + struct f81604_int_data *data) +{ + enum can_state can_state = priv->can.state; + struct net_device *netdev = priv->netdev; + struct net_device_stats *stats = &netdev->stats; + struct can_frame *cf; + struct sk_buff *skb; + + /* Note: ALC/ECC will not auto clear by read here, must be cleared by + * read register (via clear_reg_work). + */ + + skb = alloc_can_err_skb(netdev, &cf); + if (skb) { + cf->can_id |= CAN_ERR_CNT; + cf->data[6] = data->txerr; + cf->data[7] = data->rxerr; + } + + if (data->isrc & F81604_SJA1000_IRQ_DOI) { + /* data overrun interrupt */ + netdev_dbg(netdev, "data overrun interrupt\n"); + + if (skb) { + cf->can_id |= CAN_ERR_CRTL; + cf->data[1] = CAN_ERR_CRTL_RX_OVERFLOW; + } + + stats->rx_over_errors++; + stats->rx_errors++; + + set_bit(F81604_CLEAR_OVERRUN, &priv->clear_flags); + } + + if (data->isrc & F81604_SJA1000_IRQ_EI) { + /* error warning interrupt */ + netdev_dbg(netdev, "error warning interrupt\n"); + + if (data->sr & F81604_SJA1000_SR_BS) + can_state = CAN_STATE_BUS_OFF; + else if (data->sr & F81604_SJA1000_SR_ES) + can_state = CAN_STATE_ERROR_WARNING; + else + can_state = CAN_STATE_ERROR_ACTIVE; + } + + if (data->isrc & F81604_SJA1000_IRQ_BEI) { + /* bus error interrupt */ + netdev_dbg(netdev, "bus error interrupt\n"); + + priv->can.can_stats.bus_error++; + stats->rx_errors++; + + if (skb) { + cf->can_id |= CAN_ERR_PROT | CAN_ERR_BUSERROR; + + /* set error type */ + switch (data->ecc & F81604_SJA1000_ECC_MASK) { + case F81604_SJA1000_ECC_BIT: + cf->data[2] |= CAN_ERR_PROT_BIT; + break; + case F81604_SJA1000_ECC_FORM: + cf->data[2] |= CAN_ERR_PROT_FORM; + break; + case F81604_SJA1000_ECC_STUFF: + cf->data[2] |= CAN_ERR_PROT_STUFF; + break; + default: + break; + } + + /* set error location */ + cf->data[3] = data->ecc & F81604_SJA1000_ECC_SEG; + + /* Error occurred during transmission? */ + if ((data->ecc & F81604_SJA1000_ECC_DIR) == 0) + cf->data[2] |= CAN_ERR_PROT_TX; + } + + set_bit(F81604_CLEAR_ECC, &priv->clear_flags); + } + + if (data->isrc & F81604_SJA1000_IRQ_EPI) { + if (can_state == CAN_STATE_ERROR_PASSIVE) + can_state = CAN_STATE_ERROR_WARNING; + else + can_state = CAN_STATE_ERROR_PASSIVE; + + /* error passive interrupt */ + netdev_dbg(netdev, "error passive interrupt: %d\n", can_state); + } + + if (data->isrc & F81604_SJA1000_IRQ_ALI) { + /* arbitration lost interrupt */ + netdev_dbg(netdev, "arbitration lost interrupt\n"); + + priv->can.can_stats.arbitration_lost++; + + if (skb) { + cf->can_id |= CAN_ERR_LOSTARB; + cf->data[0] = data->alc & F81604_SJA1000_ALC_MASK; + } + + set_bit(F81604_CLEAR_ALC, &priv->clear_flags); + } + + if (can_state != priv->can.state) { + enum can_state tx_state, rx_state; + + tx_state = data->txerr >= data->rxerr ? can_state : 0; + rx_state = data->txerr <= data->rxerr ? can_state : 0; + + can_change_state(netdev, cf, tx_state, rx_state); + + if (can_state == CAN_STATE_BUS_OFF) + can_bus_off(netdev); + } + + if (priv->clear_flags) + schedule_work(&priv->clear_reg_work); + + if (skb) + netif_rx(skb); +} + +static void f81604_read_int_callback(struct urb *urb) +{ + struct f81604_int_data *data = urb->transfer_buffer; + struct net_device *netdev = urb->context; + struct f81604_port_priv *priv; + int ret; + + priv = netdev_priv(netdev); + + if (!netif_device_present(netdev)) + return; + + if (urb->status) + netdev_info(netdev, "%s: Int URB aborted: %pe\n", __func__, + ERR_PTR(urb->status)); + + switch (urb->status) { + case 0: /* success */ + break; + + case -ENOENT: + case -EPIPE: + case -EPROTO: + case -ESHUTDOWN: + return; + + default: + goto resubmit_urb; + } + + /* handle Errors */ + if (data->isrc & (F81604_SJA1000_IRQ_DOI | F81604_SJA1000_IRQ_EI | + F81604_SJA1000_IRQ_BEI | F81604_SJA1000_IRQ_EPI | + F81604_SJA1000_IRQ_ALI)) + f81604_handle_can_bus_errors(priv, data); + + /* handle TX */ + if (priv->can.state != CAN_STATE_BUS_OFF && + (data->isrc & F81604_SJA1000_IRQ_TI)) + f81604_handle_tx(priv, data); + +resubmit_urb: + ret = usb_submit_urb(urb, GFP_ATOMIC); + if (ret == -ENODEV) + netif_device_detach(netdev); + else if (ret) + netdev_err(netdev, "%s: failed to resubmit int urb: %pe\n", + __func__, ERR_PTR(ret)); +} + +static void f81604_unregister_urbs(struct f81604_port_priv *priv) +{ + usb_kill_anchored_urbs(&priv->urbs_anchor); +} + +static int f81604_register_urbs(struct f81604_port_priv *priv) +{ + struct net_device *netdev = priv->netdev; + struct f81604_int_data *int_data; + int id = netdev->dev_port; + struct urb *int_urb; + int rx_urb_cnt; + int ret; + + for (rx_urb_cnt = 0; rx_urb_cnt < F81604_MAX_RX_URBS; ++rx_urb_cnt) { + struct f81604_can_frame *frame; + struct urb *rx_urb; + + rx_urb = usb_alloc_urb(0, GFP_KERNEL); + if (!rx_urb) { + ret = -ENOMEM; + break; + } + + frame = kmalloc(sizeof(*frame), GFP_KERNEL); + if (!frame) { + usb_free_urb(rx_urb); + ret = -ENOMEM; + break; + } + + usb_fill_bulk_urb(rx_urb, priv->dev, + usb_rcvbulkpipe(priv->dev, bulk_in_addr[id]), + frame, sizeof(*frame), + f81604_read_bulk_callback, netdev); + + rx_urb->transfer_flags |= URB_FREE_BUFFER; + usb_anchor_urb(rx_urb, &priv->urbs_anchor); + + ret = usb_submit_urb(rx_urb, GFP_KERNEL); + if (ret) { + usb_unanchor_urb(rx_urb); + usb_free_urb(rx_urb); + break; + } + + /* Drop reference, USB core will take care of freeing it */ + usb_free_urb(rx_urb); + } + + if (rx_urb_cnt == 0) { + netdev_warn(netdev, "%s: submit rx urb failed: %pe\n", + __func__, ERR_PTR(ret)); + + goto error; + } + + int_urb = usb_alloc_urb(0, GFP_KERNEL); + if (!int_urb) { + ret = -ENOMEM; + goto error; + } + + int_data = kmalloc(sizeof(*int_data), GFP_KERNEL); + if (!int_data) { + usb_free_urb(int_urb); + ret = -ENOMEM; + goto error; + } + + usb_fill_int_urb(int_urb, priv->dev, + usb_rcvintpipe(priv->dev, int_in_addr[id]), int_data, + sizeof(*int_data), f81604_read_int_callback, netdev, + 1); + + int_urb->transfer_flags |= URB_FREE_BUFFER; + usb_anchor_urb(int_urb, &priv->urbs_anchor); + + ret = usb_submit_urb(int_urb, GFP_KERNEL); + if (ret) { + usb_unanchor_urb(int_urb); + usb_free_urb(int_urb); + + netdev_warn(netdev, "%s: submit int urb failed: %pe\n", + __func__, ERR_PTR(ret)); + goto error; + } + + /* Drop reference, USB core will take care of freeing it */ + usb_free_urb(int_urb); + + return 0; + +error: + f81604_unregister_urbs(priv); + return ret; +} + +static int f81604_start(struct net_device *netdev) +{ + struct f81604_port_priv *priv = netdev_priv(netdev); + int ret; + u8 mode; + u8 tmp; + + mode = F81604_RX_AUTO_RELEASE_BUF | F81604_INT_WHEN_CHANGE; + + /* Set TR/AT mode */ + if (priv->can.ctrlmode & CAN_CTRLMODE_ONE_SHOT) + mode |= F81604_TX_ONESHOT; + else + mode |= F81604_TX_NORMAL; + + ret = f81604_sja1000_write(priv, F81604_CTRL_MODE_REG, mode); + if (ret) + return ret; + + /* set reset mode */ + ret = f81604_set_reset_mode(priv); + if (ret) + return ret; + + ret = f81604_chipset_init(priv); + if (ret) + return ret; + + /* Clear error counters and error code capture */ + ret = f81604_sja1000_write(priv, F81604_SJA1000_TXERR, 0); + if (ret) + return ret; + + ret = f81604_sja1000_write(priv, F81604_SJA1000_RXERR, 0); + if (ret) + return ret; + + /* Read clear for ECC/ALC/IR register */ + ret = f81604_sja1000_read(priv, F81604_SJA1000_ECC, &tmp); + if (ret) + return ret; + + ret = f81604_sja1000_read(priv, F81604_SJA1000_ALC, &tmp); + if (ret) + return ret; + + ret = f81604_sja1000_read(priv, F81604_SJA1000_IR, &tmp); + if (ret) + return ret; + + ret = f81604_register_urbs(priv); + if (ret) + return ret; + + ret = f81604_set_normal_mode(priv); + if (ret) { + f81604_unregister_urbs(priv); + return ret; + } + + return 0; +} + +static int f81604_set_bittiming(struct net_device *dev) +{ + struct f81604_port_priv *priv = netdev_priv(dev); + struct can_bittiming *bt = &priv->can.bittiming; + u8 btr0, btr1; + int ret; + + btr0 = FIELD_PREP(F81604_BRP_MASK, bt->brp - 1) | + FIELD_PREP(F81604_SJW_MASK, bt->sjw - 1); + + btr1 = FIELD_PREP(F81604_SEG1_MASK, + bt->prop_seg + bt->phase_seg1 - 1) | + FIELD_PREP(F81604_SEG2_MASK, bt->phase_seg2 - 1); + + if (priv->can.ctrlmode & CAN_CTRLMODE_3_SAMPLES) + btr1 |= F81604_SJA1000_BTR1_SAMPLE_TRIPLE; + + ret = f81604_sja1000_write(priv, F81604_SJA1000_BTR0, btr0); + if (ret) { + netdev_warn(dev, "%s: Set BTR0 failed: %pe\n", __func__, + ERR_PTR(ret)); + return ret; + } + + ret = f81604_sja1000_write(priv, F81604_SJA1000_BTR1, btr1); + if (ret) { + netdev_warn(dev, "%s: Set BTR1 failed: %pe\n", __func__, + ERR_PTR(ret)); + return ret; + } + + return 0; +} + +static int f81604_set_mode(struct net_device *netdev, enum can_mode mode) +{ + int ret; + + switch (mode) { + case CAN_MODE_START: + ret = f81604_start(netdev); + if (!ret && netif_queue_stopped(netdev)) + netif_wake_queue(netdev); + break; + + default: + ret = -EOPNOTSUPP; + } + + return ret; +} + +static void f81604_write_bulk_callback(struct urb *urb) +{ + struct net_device *netdev = urb->context; + + if (!netif_device_present(netdev)) + return; + + if (urb->status) + netdev_info(netdev, "%s: Tx URB error: %pe\n", __func__, + ERR_PTR(urb->status)); +} + +static void f81604_clear_reg_work(struct work_struct *work) +{ + struct f81604_port_priv *priv; + u8 tmp; + + priv = container_of(work, struct f81604_port_priv, clear_reg_work); + + /* dummy read for clear Arbitration lost capture(ALC) register. */ + if (test_and_clear_bit(F81604_CLEAR_ALC, &priv->clear_flags)) + f81604_sja1000_read(priv, F81604_SJA1000_ALC, &tmp); + + /* dummy read for clear Error code capture(ECC) register. */ + if (test_and_clear_bit(F81604_CLEAR_ECC, &priv->clear_flags)) + f81604_sja1000_read(priv, F81604_SJA1000_ECC, &tmp); + + /* dummy write for clear data overrun flag. */ + if (test_and_clear_bit(F81604_CLEAR_OVERRUN, &priv->clear_flags)) + f81604_sja1000_write(priv, F81604_SJA1000_CMR, + F81604_SJA1000_CMD_CDO); +} + +static netdev_tx_t f81604_start_xmit(struct sk_buff *skb, + struct net_device *netdev) +{ + struct can_frame *cf = (struct can_frame *)skb->data; + struct f81604_port_priv *priv = netdev_priv(netdev); + struct net_device_stats *stats = &netdev->stats; + struct f81604_can_frame *frame; + struct urb *write_urb; + int ret; + + if (can_dev_dropped_skb(netdev, skb)) + return NETDEV_TX_OK; + + netif_stop_queue(netdev); + + write_urb = usb_alloc_urb(0, GFP_ATOMIC); + if (!write_urb) + goto nomem_urb; + + frame = kzalloc(sizeof(*frame), GFP_ATOMIC); + if (!frame) + goto nomem_buf; + + usb_fill_bulk_urb(write_urb, priv->dev, + usb_sndbulkpipe(priv->dev, + bulk_out_addr[netdev->dev_port]), + frame, sizeof(*frame), f81604_write_bulk_callback, + priv->netdev); + + write_urb->transfer_flags |= URB_FREE_BUFFER; + + frame->cmd = F81604_CMD_DATA; + frame->dlc = cf->len; + + if (cf->can_id & CAN_RTR_FLAG) + frame->dlc |= F81604_DLC_RTR_BIT; + + if (cf->can_id & CAN_EFF_FLAG) { + u32 id = (cf->can_id & CAN_EFF_MASK) << F81604_EFF_SHIFT; + + put_unaligned_be32(id, &frame->eff.id); + + frame->dlc |= F81604_DLC_EFF_BIT; + + if (!(cf->can_id & CAN_RTR_FLAG)) + memcpy(&frame->eff.data, cf->data, cf->len); + } else { + u32 id = (cf->can_id & CAN_SFF_MASK) << F81604_SFF_SHIFT; + + put_unaligned_be16(id, &frame->sff.id); + + if (!(cf->can_id & CAN_RTR_FLAG)) + memcpy(&frame->sff.data, cf->data, cf->len); + } + + can_put_echo_skb(skb, netdev, 0, 0); + + ret = usb_submit_urb(write_urb, GFP_ATOMIC); + if (ret) { + netdev_err(netdev, "%s: failed to resubmit tx bulk urb: %pe\n", + __func__, ERR_PTR(ret)); + + can_free_echo_skb(netdev, 0, NULL); + stats->tx_dropped++; + stats->tx_errors++; + + if (ret == -ENODEV) + netif_device_detach(netdev); + else + netif_wake_queue(netdev); + } + + /* let usb core take care of this urb */ + usb_free_urb(write_urb); + + return NETDEV_TX_OK; + +nomem_buf: + usb_free_urb(write_urb); + +nomem_urb: + dev_kfree_skb(skb); + stats->tx_dropped++; + stats->tx_errors++; + netif_wake_queue(netdev); + + return NETDEV_TX_OK; +} + +static int f81604_get_berr_counter(const struct net_device *netdev, + struct can_berr_counter *bec) +{ + struct f81604_port_priv *priv = netdev_priv(netdev); + u8 txerr, rxerr; + int ret; + + ret = f81604_sja1000_read(priv, F81604_SJA1000_TXERR, &txerr); + if (ret) + return ret; + + ret = f81604_sja1000_read(priv, F81604_SJA1000_RXERR, &rxerr); + if (ret) + return ret; + + bec->txerr = txerr; + bec->rxerr = rxerr; + + return 0; +} + +/* Open USB device */ +static int f81604_open(struct net_device *netdev) +{ + int ret; + + ret = open_candev(netdev); + if (ret) + return ret; + + ret = f81604_start(netdev); + if (ret) { + if (ret == -ENODEV) + netif_device_detach(netdev); + + close_candev(netdev); + return ret; + } + + netif_start_queue(netdev); + return 0; +} + +/* Close USB device */ +static int f81604_close(struct net_device *netdev) +{ + struct f81604_port_priv *priv = netdev_priv(netdev); + + f81604_set_reset_mode(priv); + + netif_stop_queue(netdev); + cancel_work_sync(&priv->clear_reg_work); + close_candev(netdev); + + f81604_unregister_urbs(priv); + + return 0; +} + +static const struct net_device_ops f81604_netdev_ops = { + .ndo_open = f81604_open, + .ndo_stop = f81604_close, + .ndo_start_xmit = f81604_start_xmit, + .ndo_change_mtu = can_change_mtu, +}; + +static const struct can_bittiming_const f81604_bittiming_const = { + .name = KBUILD_MODNAME, + .tseg1_min = 1, + .tseg1_max = 16, + .tseg2_min = 1, + .tseg2_max = 8, + .sjw_max = 4, + .brp_min = 1, + .brp_max = 64, + .brp_inc = 1, +}; + +/* Called by the usb core when driver is unloaded or device is removed */ +static void f81604_disconnect(struct usb_interface *intf) +{ + struct f81604_priv *priv = usb_get_intfdata(intf); + int i; + + for (i = 0; i < ARRAY_SIZE(priv->netdev); ++i) { + if (!priv->netdev[i]) + continue; + + unregister_netdev(priv->netdev[i]); + free_candev(priv->netdev[i]); + } +} + +static int __f81604_set_termination(struct usb_device *dev, int idx, u16 term) +{ + u8 mask, data = 0; + + if (idx == 0) + mask = F81604_CAN0_TERM; + else + mask = F81604_CAN1_TERM; + + if (term) + data = mask; + + return f81604_update_bits(dev, F81604_TERMINATOR_REG, mask, data); +} + +static int f81604_set_termination(struct net_device *netdev, u16 term) +{ + struct f81604_port_priv *port_priv = netdev_priv(netdev); + + ASSERT_RTNL(); + + return __f81604_set_termination(port_priv->dev, netdev->dev_port, + term); +} + +static int f81604_probe(struct usb_interface *intf, + const struct usb_device_id *id) +{ + struct usb_device *dev = interface_to_usbdev(intf); + struct net_device *netdev; + struct f81604_priv *priv; + int i, ret; + + priv = devm_kzalloc(&intf->dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + usb_set_intfdata(intf, priv); + + for (i = 0; i < ARRAY_SIZE(priv->netdev); ++i) { + ret = __f81604_set_termination(dev, i, 0); + if (ret) { + dev_err(&intf->dev, + "Setting termination of CH#%d failed: %pe\n", + i, ERR_PTR(ret)); + return ret; + } + } + + for (i = 0; i < ARRAY_SIZE(priv->netdev); ++i) { + struct f81604_port_priv *port_priv; + + netdev = alloc_candev(sizeof(*port_priv), 1); + if (!netdev) { + dev_err(&intf->dev, "Couldn't alloc candev: %d\n", i); + ret = -ENOMEM; + + goto failure_cleanup; + } + + port_priv = netdev_priv(netdev); + + INIT_WORK(&port_priv->clear_reg_work, f81604_clear_reg_work); + init_usb_anchor(&port_priv->urbs_anchor); + + port_priv->intf = intf; + port_priv->dev = dev; + port_priv->netdev = netdev; + port_priv->can.clock.freq = F81604_CAN_CLOCK; + + port_priv->can.termination_const = f81604_termination; + port_priv->can.termination_const_cnt = + ARRAY_SIZE(f81604_termination); + port_priv->can.bittiming_const = &f81604_bittiming_const; + port_priv->can.do_set_bittiming = f81604_set_bittiming; + port_priv->can.do_set_mode = f81604_set_mode; + port_priv->can.do_set_termination = f81604_set_termination; + port_priv->can.do_get_berr_counter = f81604_get_berr_counter; + port_priv->can.ctrlmode_supported = + CAN_CTRLMODE_LISTENONLY | CAN_CTRLMODE_3_SAMPLES | + CAN_CTRLMODE_ONE_SHOT | CAN_CTRLMODE_BERR_REPORTING | + CAN_CTRLMODE_PRESUME_ACK; + + netdev->ethtool_ops = &f81604_ethtool_ops; + netdev->netdev_ops = &f81604_netdev_ops; + netdev->flags |= IFF_ECHO; + netdev->dev_port = i; + + SET_NETDEV_DEV(netdev, &intf->dev); + + ret = register_candev(netdev); + if (ret) { + netdev_err(netdev, "register CAN device failed: %pe\n", + ERR_PTR(ret)); + free_candev(netdev); + + goto failure_cleanup; + } + + priv->netdev[i] = netdev; + } + + return 0; + +failure_cleanup: + f81604_disconnect(intf); + return ret; +} + +static struct usb_driver f81604_driver = { + .name = KBUILD_MODNAME, + .probe = f81604_probe, + .disconnect = f81604_disconnect, + .id_table = f81604_table, +}; + +module_usb_driver(f81604_driver); + +MODULE_AUTHOR("Ji-Ze Hong (Peter Hong) <peter_hong@fintek.com.tw>"); +MODULE_DESCRIPTION("Fintek F81604 USB to 2xCANBUS"); +MODULE_LICENSE("GPL"); diff --git a/drivers/net/can/usb/kvaser_usb/kvaser_usb_core.c b/drivers/net/can/usb/kvaser_usb/kvaser_usb_core.c index 7135ec851341..71ef4db5c09f 100644 --- a/drivers/net/can/usb/kvaser_usb/kvaser_usb_core.c +++ b/drivers/net/can/usb/kvaser_usb/kvaser_usb_core.c @@ -816,7 +816,7 @@ static int kvaser_usb_init_one(struct kvaser_usb *dev, int channel) init_completion(&priv->stop_comp); init_completion(&priv->flush_comp); init_completion(&priv->get_busparams_comp); - priv->can.ctrlmode_supported = 0; + priv->can.ctrlmode_supported = CAN_CTRLMODE_CC_LEN8_DLC; priv->dev = dev; priv->netdev = netdev; diff --git a/drivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c b/drivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c index ef341c4254fc..c7ba768dfe17 100644 --- a/drivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c +++ b/drivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c @@ -1263,7 +1263,7 @@ static void kvaser_usb_hydra_rx_msg_std(const struct kvaser_usb *dev, if (flags & KVASER_USB_HYDRA_CF_FLAG_OVERRUN) kvaser_usb_can_rx_over_error(priv->netdev); - cf->len = can_cc_dlc2len(cmd->rx_can.dlc); + can_frame_set_cc_len((struct can_frame *)cf, cmd->rx_can.dlc, priv->can.ctrlmode); if (flags & KVASER_USB_HYDRA_CF_FLAG_REMOTE_FRAME) { cf->can_id |= CAN_RTR_FLAG; @@ -1342,7 +1342,7 @@ static void kvaser_usb_hydra_rx_msg_ext(const struct kvaser_usb *dev, if (flags & KVASER_USB_HYDRA_CF_FLAG_ESI) cf->flags |= CANFD_ESI; } else { - cf->len = can_cc_dlc2len(dlc); + can_frame_set_cc_len((struct can_frame *)cf, dlc, priv->can.ctrlmode); } if (flags & KVASER_USB_HYDRA_CF_FLAG_REMOTE_FRAME) { @@ -1442,7 +1442,7 @@ kvaser_usb_hydra_frame_to_cmd_ext(const struct kvaser_usb_net_priv *priv, struct kvaser_usb *dev = priv->dev; struct kvaser_cmd_ext *cmd; struct canfd_frame *cf = (struct canfd_frame *)skb->data; - u8 dlc = can_fd_len2dlc(cf->len); + u8 dlc; u8 nbr_of_bytes = cf->len; u32 flags; u32 id; @@ -1467,6 +1467,11 @@ kvaser_usb_hydra_frame_to_cmd_ext(const struct kvaser_usb_net_priv *priv, cmd->len = cpu_to_le16(*cmd_len); + if (can_is_canfd_skb(skb)) + dlc = can_fd_len2dlc(cf->len); + else + dlc = can_get_cc_dlc((struct can_frame *)cf, priv->can.ctrlmode); + cmd->tx_can.databytes = nbr_of_bytes; cmd->tx_can.dlc = dlc; @@ -1542,7 +1547,7 @@ kvaser_usb_hydra_frame_to_cmd_std(const struct kvaser_usb_net_priv *priv, id = cf->can_id & CAN_SFF_MASK; } - cmd->tx_can.dlc = cf->len; + cmd->tx_can.dlc = can_get_cc_dlc(cf, priv->can.ctrlmode); flags = (cf->can_id & CAN_EFF_FLAG ? KVASER_USB_HYDRA_CF_FLAG_EXTENDED_ID : 0); diff --git a/drivers/net/can/usb/kvaser_usb/kvaser_usb_leaf.c b/drivers/net/can/usb/kvaser_usb/kvaser_usb_leaf.c index 1c2f99ce4c6c..23bd7574b1c7 100644 --- a/drivers/net/can/usb/kvaser_usb/kvaser_usb_leaf.c +++ b/drivers/net/can/usb/kvaser_usb/kvaser_usb_leaf.c @@ -573,7 +573,7 @@ kvaser_usb_leaf_frame_to_cmd(const struct kvaser_usb_net_priv *priv, cmd->u.tx_can.data[1] = cf->can_id & 0x3f; } - cmd->u.tx_can.data[5] = cf->len; + cmd->u.tx_can.data[5] = can_get_cc_dlc(cf, priv->can.ctrlmode); memcpy(&cmd->u.tx_can.data[6], cf->data, cf->len); if (cf->can_id & CAN_RTR_FLAG) @@ -1349,7 +1349,7 @@ static void kvaser_usb_leaf_rx_can_msg(const struct kvaser_usb *dev, else cf->can_id &= CAN_SFF_MASK; - cf->len = can_cc_dlc2len(cmd->u.leaf.log_message.dlc); + can_frame_set_cc_len(cf, cmd->u.leaf.log_message.dlc & 0xF, priv->can.ctrlmode); if (cmd->u.leaf.log_message.flags & MSG_FLAG_REMOTE_FRAME) cf->can_id |= CAN_RTR_FLAG; @@ -1367,7 +1367,7 @@ static void kvaser_usb_leaf_rx_can_msg(const struct kvaser_usb *dev, cf->can_id |= CAN_EFF_FLAG; } - cf->len = can_cc_dlc2len(rx_data[5]); + can_frame_set_cc_len(cf, rx_data[5] & 0xF, priv->can.ctrlmode); if (cmd->u.rx_can_header.flag & MSG_FLAG_REMOTE_FRAME) cf->can_id |= CAN_RTR_FLAG; |