Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 0a25e1f4 authored by Stephane Grosjean's avatar Stephane Grosjean Committed by Marc Kleine-Budde
Browse files

can: peak_usb: add support for PEAK new CANFD USB adapters



Add support for the following new PEAK-System technik CANFD USB adapters:

PCAN-USB FD             single CANFD channel USB adapter
PCAN-USB Pro FD         dual CANFD channels USB adapter

Signed-off-by: default avatarStephane Grosjean <s.grosjean@peak-system.com>
Signed-off-by: default avatarOliver Hartkopp <socketcan@hartkopp.net>
Acked-by: default avatarAndri Yngvason <andri.yngvason@marel.com>
Signed-off-by: default avatarMarc Kleine-Budde <mkl@pengutronix.de>
parent faa233d9
Loading
Loading
Loading
Loading
+11 −3
Original line number Original line Diff line number Diff line
@@ -59,10 +59,18 @@ config CAN_KVASER_USB
	  module will be called kvaser_usb.
	  module will be called kvaser_usb.


config CAN_PEAK_USB
config CAN_PEAK_USB
	tristate "PEAK PCAN-USB/USB Pro interfaces"
	tristate "PEAK PCAN-USB/USB Pro interfaces for CAN 2.0b/CAN-FD"
	---help---
	---help---
	  This driver supports the PCAN-USB and PCAN-USB Pro adapters
	  This driver supports the PEAK-System Technik USB adapters that enable
	  from PEAK-System Technik (http://www.peak-system.com).
	  access to the CAN bus, with repect to the CAN 2.0b and/or CAN-FD
	  standards, that is:

	  PCAN-USB             single CAN 2.0b channel USB adapter
	  PCAN-USB Pro         dual CAN 2.0b channels USB adapter
	  PCAN-USB FD          single CAN-FD channel USB adapter
	  PCAN-USB Pro FD      dual CAN-FD channels USB adapter

	  (see also http://www.peak-system.com).


config CAN_8DEV_USB
config CAN_8DEV_USB
	tristate "8 devices USB2CAN interface"
	tristate "8 devices USB2CAN interface"
+1 −1
Original line number Original line Diff line number Diff line
obj-$(CONFIG_CAN_PEAK_USB) += peak_usb.o
obj-$(CONFIG_CAN_PEAK_USB) += peak_usb.o
peak_usb-y = pcan_usb_core.o pcan_usb.o pcan_usb_pro.o
peak_usb-y = pcan_usb_core.o pcan_usb.o pcan_usb_pro.o pcan_usb_fd.o
+222 −0
Original line number Original line Diff line number Diff line
/*
 * CAN driver for PEAK System micro-CAN based adapters
 *
 * Copyright (C) 2003-2011 PEAK System-Technik GmbH
 * Copyright (C) 2011-2013 Stephane Grosjean <s.grosjean@peak-system.com>
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published
 * by the Free Software Foundation; version 2 of the License.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 */
#ifndef PUCAN_H
#define PUCAN_H

/* uCAN commands opcodes list (low-order 10 bits) */
#define PUCAN_CMD_NOP			0x000
#define PUCAN_CMD_RESET_MODE		0x001
#define PUCAN_CMD_NORMAL_MODE		0x002
#define PUCAN_CMD_LISTEN_ONLY_MODE	0x003
#define PUCAN_CMD_TIMING_SLOW		0x004
#define PUCAN_CMD_TIMING_FAST		0x005
#define PUCAN_CMD_FILTER_STD		0x008
#define PUCAN_CMD_TX_ABORT		0x009
#define PUCAN_CMD_WR_ERR_CNT		0x00a
#define PUCAN_CMD_RX_FRAME_ENABLE	0x00b
#define PUCAN_CMD_RX_FRAME_DISABLE	0x00c
#define PUCAN_CMD_END_OF_COLLECTION	0x3ff

/* uCAN received messages list */
#define PUCAN_MSG_CAN_RX		0x0001
#define PUCAN_MSG_ERROR			0x0002
#define PUCAN_MSG_STATUS		0x0003
#define PUCAN_MSG_BUSLOAD		0x0004
#define PUCAN_MSG_CAN_TX		0x1000

/* uCAN command common header */
struct __packed pucan_command {
	__le16	opcode_channel;
	u16	args[3];
};

/* uCAN TIMING_SLOW command fields */
#define PUCAN_TSLOW_SJW_T(s, t)		(((s) & 0xf) | ((!!(t)) << 7))
#define PUCAN_TSLOW_TSEG2(t)		((t) & 0xf)
#define PUCAN_TSLOW_TSEG1(t)		((t) & 0x3f)
#define PUCAN_TSLOW_BRP(b)		((b) & 0x3ff)

struct __packed pucan_timing_slow {
	__le16	opcode_channel;

	u8	ewl;		/* Error Warning limit */
	u8	sjw_t;		/* Sync Jump Width + Triple sampling */
	u8	tseg2;		/* Timing SEGment 2 */
	u8	tseg1;		/* Timing SEGment 1 */

	__le16	brp;		/* BaudRate Prescaler */
};

/* uCAN TIMING_FAST command fields */
#define PUCAN_TFAST_SJW(s)		((s) & 0x3)
#define PUCAN_TFAST_TSEG2(t)		((t) & 0x7)
#define PUCAN_TFAST_TSEG1(t)		((t) & 0xf)
#define PUCAN_TFAST_BRP(b)		((b) & 0x3ff)

struct __packed pucan_timing_fast {
	__le16	opcode_channel;

	u8	unused;
	u8	sjw;		/* Sync Jump Width */
	u8	tseg2;		/* Timing SEGment 2 */
	u8	tseg1;		/* Timing SEGment 1 */

	__le16	brp;		/* BaudRate Prescaler */
};

/* uCAN FILTER_STD command fields */
#define PUCAN_FLTSTD_ROW_IDX_BITS	6

struct __packed pucan_filter_std {
	__le16	opcode_channel;

	__le16	idx;
	__le32	mask;		/* CAN-ID bitmask in idx range */
};

/* uCAN WR_ERR_CNT command fields */
#define PUCAN_WRERRCNT_TE		0x4000	/* Tx error cntr write Enable */
#define PUCAN_WRERRCNT_RE		0x8000	/* Rx error cntr write Enable */

struct __packed pucan_wr_err_cnt {
	__le16	opcode_channel;

	__le16	sel_mask;
	u8	tx_counter;	/* Tx error counter new value */
	u8	rx_counter;	/* Rx error counter new value */

	u16	unused;
};

/* uCAN RX_FRAME_ENABLE command fields */
#define PUCAN_FLTEXT_ERROR		0x0001
#define PUCAN_FLTEXT_BUSLOAD		0x0002

struct __packed pucan_filter_ext {
	__le16	opcode_channel;

	__le16	ext_mask;
	u32	unused;
};

/* uCAN received messages global format */
struct __packed pucan_msg {
	__le16	size;
	__le16	type;
	__le32	ts_low;
	__le32	ts_high;
};

/* uCAN flags for CAN/CANFD messages */
#define PUCAN_MSG_SELF_RECEIVE		0x80
#define PUCAN_MSG_ERROR_STATE_IND	0x40	/* error state indicator */
#define PUCAN_MSG_BITRATE_SWITCH	0x20	/* bitrate switch */
#define PUCAN_MSG_EXT_DATA_LEN		0x10	/* extended data length */
#define PUCAN_MSG_SINGLE_SHOT		0x08
#define PUCAN_MSG_LOOPED_BACK		0x04
#define PUCAN_MSG_EXT_ID		0x02
#define PUCAN_MSG_RTR			0x01

struct __packed pucan_rx_msg {
	__le16	size;
	__le16	type;
	__le32	ts_low;
	__le32	ts_high;
	__le32	tag_low;
	__le32	tag_high;
	u8	channel_dlc;
	u8	client;
	__le16	flags;
	__le32	can_id;
	u8	d[0];
};

/* uCAN error types */
#define PUCAN_ERMSG_BIT_ERROR		0
#define PUCAN_ERMSG_FORM_ERROR		1
#define PUCAN_ERMSG_STUFF_ERROR		2
#define PUCAN_ERMSG_OTHER_ERROR		3
#define PUCAN_ERMSG_ERR_CNT_DEC		4

struct __packed pucan_error_msg {
	__le16	size;
	__le16	type;
	__le32	ts_low;
	__le32	ts_high;
	u8	channel_type_d;
	u8	code_g;
	u8	tx_err_cnt;
	u8	rx_err_cnt;
};

#define PUCAN_BUS_PASSIVE		0x20
#define PUCAN_BUS_WARNING		0x40
#define PUCAN_BUS_BUSOFF		0x80

struct __packed pucan_status_msg {
	__le16	size;
	__le16	type;
	__le32	ts_low;
	__le32	ts_high;
	u8	channel_p_w_b;
	u8	unused[3];
};

/* uCAN transmitted message format */
#define PUCAN_MSG_CHANNEL_DLC(c, d)	(((c) & 0xf) | ((d) << 4))

struct __packed pucan_tx_msg {
	__le16	size;
	__le16	type;
	__le32	tag_low;
	__le32	tag_high;
	u8	channel_dlc;
	u8	client;
	__le16	flags;
	__le32	can_id;
	u8	d[0];
};

/* build the cmd opcode_channel field with respect to the correct endianness */
static inline __le16 pucan_cmd_opcode_channel(struct peak_usb_device *dev,
					      int opcode)
{
	return cpu_to_le16(((dev->ctrl_idx) << 12) | ((opcode) & 0x3ff));
}

/* return the channel number part from any received message channel_dlc field */
static inline int pucan_msg_get_channel(struct pucan_rx_msg *rm)
{
	return rm->channel_dlc & 0xf;
}

/* return the dlc value from any received message channel_dlc field */
static inline int pucan_msg_get_dlc(struct pucan_rx_msg *rm)
{
	return rm->channel_dlc >> 4;
}

static inline int pucan_ermsg_get_channel(struct pucan_error_msg *em)
{
	return em->channel_type_d & 0x0f;
}

static inline int pucan_stmsg_get_channel(struct pucan_status_msg *sm)
{
	return sm->channel_p_w_b & 0x0f;
}

#endif
+4 −0
Original line number Original line Diff line number Diff line
@@ -37,6 +37,8 @@ MODULE_LICENSE("GPL v2");
static struct usb_device_id peak_usb_table[] = {
static struct usb_device_id peak_usb_table[] = {
	{USB_DEVICE(PCAN_USB_VENDOR_ID, PCAN_USB_PRODUCT_ID)},
	{USB_DEVICE(PCAN_USB_VENDOR_ID, PCAN_USB_PRODUCT_ID)},
	{USB_DEVICE(PCAN_USB_VENDOR_ID, PCAN_USBPRO_PRODUCT_ID)},
	{USB_DEVICE(PCAN_USB_VENDOR_ID, PCAN_USBPRO_PRODUCT_ID)},
	{USB_DEVICE(PCAN_USB_VENDOR_ID, PCAN_USBFD_PRODUCT_ID)},
	{USB_DEVICE(PCAN_USB_VENDOR_ID, PCAN_USBPROFD_PRODUCT_ID)},
	{} /* Terminating entry */
	{} /* Terminating entry */
};
};


@@ -46,6 +48,8 @@ MODULE_DEVICE_TABLE(usb, peak_usb_table);
static const struct peak_usb_adapter *const peak_usb_adapters_list[] = {
static const struct peak_usb_adapter *const peak_usb_adapters_list[] = {
	&pcan_usb,
	&pcan_usb,
	&pcan_usb_pro,
	&pcan_usb_pro,
	&pcan_usb_fd,
	&pcan_usb_pro_fd,
};
};


/*
/*
+4 −0
Original line number Original line Diff line number Diff line
@@ -25,6 +25,8 @@
/* supported device ids. */
/* supported device ids. */
#define PCAN_USB_PRODUCT_ID		0x000c
#define PCAN_USB_PRODUCT_ID		0x000c
#define PCAN_USBPRO_PRODUCT_ID		0x000d
#define PCAN_USBPRO_PRODUCT_ID		0x000d
#define PCAN_USBPROFD_PRODUCT_ID	0x0011
#define PCAN_USBFD_PRODUCT_ID		0x0012


#define PCAN_USB_DRIVER_NAME		"peak_usb"
#define PCAN_USB_DRIVER_NAME		"peak_usb"


@@ -86,6 +88,8 @@ struct peak_usb_adapter {


extern const struct peak_usb_adapter pcan_usb;
extern const struct peak_usb_adapter pcan_usb;
extern const struct peak_usb_adapter pcan_usb_pro;
extern const struct peak_usb_adapter pcan_usb_pro;
extern const struct peak_usb_adapter pcan_usb_fd;
extern const struct peak_usb_adapter pcan_usb_pro_fd;


struct peak_time_ref {
struct peak_time_ref {
	struct timeval tv_host_0, tv_host;
	struct timeval tv_host_0, tv_host;
Loading