aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/can/usb/etas_es58x/es58x_fd.h
blob: a191891b8777657f20ed18c52a15f2329f207f59 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
/* SPDX-License-Identifier: GPL-2.0 */

/* Driver for ETAS GmbH ES58X USB CAN(-FD) Bus Interfaces.
 *
 * File es58x_fd.h: Definitions and declarations specific to ETAS
 * ES582.1 and ES584.1 (naming convention: we use the term "ES58X FD"
 * when referring to those two variants together).
 *
 * Copyright (c) 2019 Robert Bosch Engineering and Business Solutions. All rights reserved.
 * Copyright (c) 2020 ETAS K.K.. All rights reserved.
 * Copyright (c) 2020, 2021 Vincent Mailhol <mailhol.vincent@wanadoo.fr>
 */

#ifndef __ES58X_FD_H__
#define __ES58X_FD_H__

#include <linux/types.h>

#define ES582_1_NUM_CAN_CH 2
#define ES584_1_NUM_CAN_CH 1
#define ES58X_FD_NUM_CAN_CH 2
#define ES58X_FD_CHANNEL_IDX_OFFSET 0

#define ES58X_FD_TX_BULK_MAX 100
#define ES58X_FD_RX_BULK_MAX 100
#define ES58X_FD_ECHO_BULK_MAX 100

enum es58x_fd_cmd_type {
	ES58X_FD_CMD_TYPE_CAN = 0x03,
	ES58X_FD_CMD_TYPE_CANFD = 0x04,
	ES58X_FD_CMD_TYPE_DEVICE = 0xFF
};

/* Command IDs for ES58X_FD_CMD_TYPE_{CAN,CANFD}. */
enum es58x_fd_can_cmd_id {
	ES58X_FD_CAN_CMD_ID_ENABLE_CHANNEL = 0x01,
	ES58X_FD_CAN_CMD_ID_DISABLE_CHANNEL = 0x02,
	ES58X_FD_CAN_CMD_ID_TX_MSG = 0x05,
	ES58X_FD_CAN_CMD_ID_ECHO_MSG = 0x07,
	ES58X_FD_CAN_CMD_ID_RX_MSG = 0x10,
	ES58X_FD_CAN_CMD_ID_ERROR_OR_EVENT_MSG = 0x11,
	ES58X_FD_CAN_CMD_ID_RESET_RX = 0x20,
	ES58X_FD_CAN_CMD_ID_RESET_TX = 0x21,
	ES58X_FD_CAN_CMD_ID_TX_MSG_NO_ACK = 0x55
};

/* Command IDs for ES58X_FD_CMD_TYPE_DEVICE. */
enum es58x_fd_dev_cmd_id {
	ES58X_FD_DEV_CMD_ID_GETTIMETICKS = 0x01,
	ES58X_FD_DEV_CMD_ID_TIMESTAMP = 0x02
};

/**
 * enum es58x_fd_ctrlmode - Controller mode.
 * @ES58X_FD_CTRLMODE_ACTIVE: send and receive messages.
 * @ES58X_FD_CTRLMODE_PASSIVE: only receive messages (monitor). Do not
 *	send anything, not even the acknowledgment bit.
 * @ES58X_FD_CTRLMODE_FD: CAN FD according to ISO11898-1.
 * @ES58X_FD_CTRLMODE_FD_NON_ISO: follow Bosch CAN FD Specification
 *	V1.0
 * @ES58X_FD_CTRLMODE_DISABLE_PROTOCOL_EXCEPTION_HANDLING: How to
 *	behave when CAN FD reserved bit is monitored as
 *	dominant. (c.f. ISO 11898-1:2015, section 10.4.2.4 "Control
 *	field", paragraph "r0 bit"). 0 (not disable = enable): send
 *	error frame. 1 (disable): goes into bus integration mode
 *	(c.f. below).
 * @ES58X_FD_CTRLMODE_EDGE_FILTER_DURING_BUS_INTEGRATION: 0: Edge
 *	filtering is disabled. 1: Edge filtering is enabled. Two
 *	consecutive dominant bits required to detect an edge for hard
 *	synchronization.
 */
enum es58x_fd_ctrlmode {
	ES58X_FD_CTRLMODE_ACTIVE = 0,
	ES58X_FD_CTRLMODE_PASSIVE = BIT(0),
	ES58X_FD_CTRLMODE_FD = BIT(4),
	ES58X_FD_CTRLMODE_FD_NON_ISO = BIT(5),
	ES58X_FD_CTRLMODE_DISABLE_PROTOCOL_EXCEPTION_HANDLING = BIT(6),
	ES58X_FD_CTRLMODE_EDGE_FILTER_DURING_BUS_INTEGRATION = BIT(7)
};

struct es58x_fd_bittiming {
	__le32 bitrate;
	__le16 tseg1;		/* range: [tseg1_min-1..tseg1_max-1] */
	__le16 tseg2;		/* range: [tseg2_min-1..tseg2_max-1] */
	__le16 brp;		/* range: [brp_min-1..brp_max-1] */
	__le16 sjw;		/* range: [0..sjw_max-1] */
} __packed;

/**
 * struct es58x_fd_tx_conf_msg - Channel configuration.
 * @nominal_bittiming: Nominal bittiming.
 * @samples_per_bit: type enum es58x_samples_per_bit.
 * @sync_edge: type enum es58x_sync_edge.
 * @physical_layer: type enum es58x_physical_layer.
 * @echo_mode: type enum es58x_echo_mode.
 * @ctrlmode: type enum es58x_fd_ctrlmode.
 * @canfd_enabled: boolean (0: Classical CAN, 1: CAN and/or CANFD).
 * @data_bittiming: Bittiming for flexible data-rate transmission.
 * @tdc_enabled: Transmitter Delay Compensation switch (0: TDC is
 *	disabled, 1: TDC is enabled).
 * @tdco: Transmitter Delay Compensation Offset.
 * @tdcf: Transmitter Delay Compensation Filter window.
 *
 * Please refer to the microcontroller datasheet: "SAM E70/S70/V70/V71
 * Family" section 49 "Controller Area Network (MCAN)" for additional
 * information.
 */
struct es58x_fd_tx_conf_msg {
	struct es58x_fd_bittiming nominal_bittiming;
	u8 samples_per_bit;
	u8 sync_edge;
	u8 physical_layer;
	u8 echo_mode;
	u8 ctrlmode;
	u8 canfd_enabled;
	struct es58x_fd_bittiming data_bittiming;
	u8 tdc_enabled;
	__le16 tdco;
	__le16 tdcf;
} __packed;

#define ES58X_FD_CAN_CONF_LEN					\
	(offsetof(struct es58x_fd_tx_conf_msg, canfd_enabled))
#define ES58X_FD_CANFD_CONF_LEN (sizeof(struct es58x_fd_tx_conf_msg))

struct es58x_fd_tx_can_msg {
	u8 packet_idx;
	__le32 can_id;
	u8 flags;
	union {
		u8 dlc;		/* Only if cmd_id is ES58X_FD_CMD_TYPE_CAN */
		u8 len;		/* Only if cmd_id is ES58X_FD_CMD_TYPE_CANFD */
	} __packed;
	u8 data[CANFD_MAX_DLEN];
} __packed;

#define ES58X_FD_CAN_TX_LEN						\
	(offsetof(struct es58x_fd_tx_can_msg, data[CAN_MAX_DLEN]))
#define ES58X_FD_CANFD_TX_LEN (sizeof(struct es58x_fd_tx_can_msg))

struct es58x_fd_rx_can_msg {
	__le64 timestamp;
	__le32 can_id;
	u8 flags;
	union {
		u8 dlc;		/* Only if cmd_id is ES58X_FD_CMD_TYPE_CAN */
		u8 len;		/* Only if cmd_id is ES58X_FD_CMD_TYPE_CANFD */
	} __packed;
	u8 data[CANFD_MAX_DLEN];
} __packed;

#define ES58X_FD_CAN_RX_LEN						\
	(offsetof(struct es58x_fd_rx_can_msg, data[CAN_MAX_DLEN]))
#define ES58X_FD_CANFD_RX_LEN (sizeof(struct es58x_fd_rx_can_msg))

struct es58x_fd_echo_msg {
	__le64 timestamp;
	u8 packet_idx;
} __packed;

struct es58x_fd_rx_event_msg {
	__le64 timestamp;
	__le32 can_id;
	u8 flags;		/* type enum es58x_flag */
	u8 error_type;		/* 0: event, 1: error */
	u8 error_code;
	u8 event_code;
} __packed;

struct es58x_fd_tx_ack_msg {
	__le32 rx_cmd_ret_le32;	/* type enum es58x_cmd_ret_code_u32 */
	__le16 tx_free_entries;	/* Number of remaining free entries in the device TX queue */
} __packed;

/**
 * struct es58x_fd_urb_cmd - Commands received from or sent to the
 *	ES58X FD device.
 * @SOF: Start of Frame.
 * @cmd_type: Command Type (type: enum es58x_fd_cmd_type). The CRC
 *	calculation starts at this position.
 * @cmd_id: Command ID (type: enum es58x_fd_cmd_id).
 * @channel_idx: Channel index starting at 0.
 * @msg_len: Length of the message, excluding CRC (i.e. length of the
 *	union).
 * @tx_conf_msg: Channel configuration.
 * @tx_can_msg_buf: Concatenation of Tx messages. Type is "u8[]"
 *	instead of "struct es58x_fd_tx_msg[]" because the structure
 *	has a flexible size.
 * @rx_can_msg_buf: Concatenation Rx messages. Type is "u8[]" instead
 *	of "struct es58x_fd_rx_msg[]" because the structure has a
 *	flexible size.
 * @echo_msg: Array of echo messages (e.g. Tx messages being looped
 *	back).
 * @rx_event_msg: Error or event message.
 * @tx_ack_msg: Tx acknowledgment message.
 * @timestamp: Timestamp reply.
 * @rx_cmd_ret_le32: Rx 32 bits return code (type: enum
 *	es58x_cmd_ret_code_u32).
 * @raw_msg: Message raw payload.
 * @reserved_for_crc16_do_not_use: The structure ends with a
 *	CRC16. Because the structures in above union are of variable
 *	lengths, we can not predict the offset of the CRC in
 *	advance. Use functions es58x_get_crc() and es58x_set_crc() to
 *	manipulate it.
 */
struct es58x_fd_urb_cmd {
	__le16 SOF;
	u8 cmd_type;
	u8 cmd_id;
	u8 channel_idx;
	__le16 msg_len;

	union {
		struct es58x_fd_tx_conf_msg tx_conf_msg;
		u8 tx_can_msg_buf[ES58X_FD_TX_BULK_MAX * ES58X_FD_CANFD_TX_LEN];
		u8 rx_can_msg_buf[ES58X_FD_RX_BULK_MAX * ES58X_FD_CANFD_RX_LEN];
		struct es58x_fd_echo_msg echo_msg[ES58X_FD_ECHO_BULK_MAX];
		struct es58x_fd_rx_event_msg rx_event_msg;
		struct es58x_fd_tx_ack_msg tx_ack_msg;
		__le64 timestamp;
		__le32 rx_cmd_ret_le32;
		u8 raw_msg[0];
	} __packed;

	__le16 reserved_for_crc16_do_not_use;
} __packed;

#define ES58X_FD_URB_CMD_HEADER_LEN (offsetof(struct es58x_fd_urb_cmd, raw_msg))
#define ES58X_FD_TX_URB_CMD_MAX_LEN					\
	ES58X_SIZEOF_URB_CMD(struct es58x_fd_urb_cmd, tx_can_msg_buf)
#define ES58X_FD_RX_URB_CMD_MAX_LEN					\
	ES58X_SIZEOF_URB_CMD(struct es58x_fd_urb_cmd, rx_can_msg_buf)

#endif /* __ES58X_FD_H__ */