// SPDX-License-Identifier: GPL-2.0-only
/* CAN driver for Geschwister Schneider USB/CAN devices
* and bytewerk.org candleLight USB CAN interfaces.
*
* Copyright (C) 2013-2016 Geschwister Schneider Technologie-,
* Entwicklungs- und Vertriebs UG (Haftungsbeschränkt).
* Copyright (C) 2016 Hubert Denkmair
*
* Many thanks to all socketcan devs!
*/
#include <linux/init.h>
#include <linux/signal.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>
/* Device specific constants */
#define USB_GSUSB_1_VENDOR_ID 0x1d50
#define USB_GSUSB_1_PRODUCT_ID 0x606f
#define USB_CANDLELIGHT_VENDOR_ID 0x1209
#define USB_CANDLELIGHT_PRODUCT_ID 0x2323
#define GSUSB_ENDPOINT_IN 1
#define GSUSB_ENDPOINT_OUT 2
/* Device specific constants */
enum gs_usb_breq {
GS_USB_BREQ_HOST_FORMAT = 0,
GS_USB_BREQ_BITTIMING,
GS_USB_BREQ_MODE,
GS_USB_BREQ_BERR,
GS_USB_BREQ_BT_CONST,
GS_USB_BREQ_DEVICE_CONFIG,
GS_USB_BREQ_TIMESTAMP,
GS_USB_BREQ_IDENTIFY,
};
enum gs_can_mode {
/* reset a channel. turns it off */
GS_CAN_MODE_RESET = 0,
/* starts a channel */
GS_CAN_MODE_START
};
enum gs_can_state {
GS_CAN_STATE_ERROR_ACTIVE = 0,
GS_CAN_STATE_ERROR_WARNING,
GS_CAN_STATE_ERROR_PASSIVE,
GS_CAN_STATE_BUS_OFF,
GS_CAN_STATE_STOPPED,
GS_CAN_STATE_SLEEPING
};
enum gs_can_identify_mode {
GS_CAN_IDENTIFY_OFF = 0,
GS_CAN_IDENTIFY_ON
};
/* data types passed between host and device */
/* The firmware on the original USB2CAN by Geschwister Schneider
* Technologie Entwicklungs- und Vertriebs UG exchanges all data
* between the host and the device in host byte order. This is done
* with the struct gs_host_config::byte_order member, which is sent
* first to indicate the desired byte order.
*
* The widely used open source firmware candleLight doesn't support
* this feature and exchanges the data in little endian byte order.
*/
struct gs_host_config {
__le32 byte_order;
} __packed;
struct gs_device_config {
u8 reserved1;
u8 reserved2;
u8 reserved3;
u8 icount;
__le32 sw_version;
__le32 hw_version;
} __packed;
#define GS_CAN_MODE_NORMAL 0
#define GS_CAN_MODE_LISTEN_ONLY BIT(0)
#define GS_CAN_MODE_LOOP_BACK BIT(1)
#define GS_CAN_MODE_TRIPLE_SAMPLE BIT(2)
#define GS_CAN_MODE_ONE_SHOT BIT(3)
struct gs_device_mode {
__le32 mode;
__le32 flags;
} __packed;
struct gs_device_state {
__le32 state;
__le32 rxerr;
__le32 txerr;
} __packed;
struct gs_device_bittiming {
__le32 prop_seg;
__le32 phase_seg1;
__le32 phase_seg2;
__le32 sjw;
__le32 brp;
} __packed;
struct gs_identify_mode {
__le32 mode;
} __packed;
#define GS_CAN_FEATURE_LISTEN_ONLY BIT(0)
#define GS_CAN_FEATURE_LOOP_BACK BIT(1)
#define GS_CAN_FEATURE_TRIPLE_SAMPLE BIT(2)
#define GS_CAN_FEATURE_ONE_SHOT BIT(3)
#define GS_CAN_FEATURE_HW_TIMESTAMP BIT(4)
#define GS_CAN_FEATURE_IDENTIFY BIT(5)
struct gs_device_bt_const {
__le32 feature;
__le32 fclk_can;
__le32 tseg1_min;
__le32 tseg1_max;
__le32 tseg2_min;
__le32 tseg2_max;
__le32 sjw_max;
__le32 brp_min;
__le32 brp_max;
__le32 brp_inc;
} __packed;
#define GS_CAN_FLAG_OVERFLOW 1
struct gs_host_frame {
u32 echo_id;
__le32 can_id;
u8 can_dlc;
u8 channel;
u8 flags;
u8 reserved;
u8 data[8];
} __packed;
/* The GS USB devices make use of the same flags and masks as in
* linux/can.h and linux/can/error.h, and no additional mapping is necessary.
*/
/* Only send a max of GS_MAX_TX_URBS frames per channel at a time. */
#define GS_MAX_TX_URBS 10
/* Only launch a max of GS_MAX_RX_URBS usb requests at a time. */
#define GS_MAX_RX_URBS 30
/* Maximum number of interfaces the driver supports per device.
* Current hardware only supports 2 interfaces. The future may vary.
*/
#define GS_MAX_INTF 2
struct gs_tx_context {
struct gs_can *dev;
unsigned int echo_id;
};
struct gs_can {
struct can_priv can; /* must be the first member */
struct gs_usb *parent;
struct net_device *netdev;
struct usb_device *udev;
struct usb_interface *iface;
struct can_bittiming_const bt_const;
unsigned int channel; /* channel number */
/* This lock prevents a race condition between xmit and receive. */
spinlock_t tx_ctx_lock;
struct gs_tx_context tx_context[GS_MAX_TX_URBS];
struct usb_anchor tx_submitted;
atomic_t active_tx_urbs;
};
/* usb interface struct */
struct gs_usb {
struct gs_can *canch[GS_MAX_INTF];
struct usb_anchor rx_submitted;
atomic_t active_channels;
struct usb_device *udev;
};
/* 'allocate' a tx context.
* returns a valid tx context or NULL if there is no space.
*/
static struct gs_tx_context *gs_alloc_tx_context(struct gs_can *dev)
{
int i = 0;
unsigned long flags;
spin_lock_irqsave(&dev->tx_ctx_lock, flags);
for (; i < GS_MAX_TX_URBS; i++) {
if (dev->tx_context[i].echo_id == GS_MAX_TX_URBS) {
dev->tx_context[i].echo_id = i;
spin_unlock_irqrestore(&dev->tx_ctx_lock, flags);
return