summaryrefslogtreecommitdiff
path: root/include/linux/can/dev/peak_canfd.h
blob: 46dceef2cfa6c0efa6d4a52df5467dba6b6a7c2c (plain)
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
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
/*
 * 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_SET_STD_FILTER	0x006
#define PUCAN_CMD_RESERVED2		0x007
#define PUCAN_CMD_FILTER_STD		0x008
#define PUCAN_CMD_TX_ABORT		0x009
#define PUCAN_CMD_WR_ERR_CNT		0x00a
#define PUCAN_CMD_SET_EN_OPTION		0x00b
#define PUCAN_CMD_CLR_DIS_OPTION	0x00c
#define PUCAN_CMD_RX_BARRIER		0x010
#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_CACHE_CRITICAL	0x0102

/* uCAN transmitted messages */
#define PUCAN_MSG_CAN_TX		0x1000

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

/* return the opcode from the opcode_channel field of a command */
static inline u16 pucan_cmd_get_opcode(struct pucan_command *c)
{
	return le16_to_cpu(c->opcode_channel) & 0x3ff;
}

#define PUCAN_TSLOW_BRP_BITS		10
#define PUCAN_TSLOW_TSGEG1_BITS		8
#define PUCAN_TSLOW_TSGEG2_BITS		7
#define PUCAN_TSLOW_SJW_BITS		7

#define PUCAN_TSLOW_BRP_MASK		((1 << PUCAN_TSLOW_BRP_BITS) - 1)
#define PUCAN_TSLOW_TSEG1_MASK		((1 << PUCAN_TSLOW_TSGEG1_BITS) - 1)
#define PUCAN_TSLOW_TSEG2_MASK		((1 << PUCAN_TSLOW_TSGEG2_BITS) - 1)
#define PUCAN_TSLOW_SJW_MASK		((1 << PUCAN_TSLOW_SJW_BITS) - 1)

/* uCAN TIMING_SLOW command fields */
#define PUCAN_TSLOW_SJW_T(s, t)		(((s) & PUCAN_TSLOW_SJW_MASK) | \
								((!!(t)) << 7))
#define PUCAN_TSLOW_TSEG2(t)		((t) & PUCAN_TSLOW_TSEG2_MASK)
#define PUCAN_TSLOW_TSEG1(t)		((t) & PUCAN_TSLOW_TSEG1_MASK)
#define PUCAN_TSLOW_BRP(b)		((b) & PUCAN_TSLOW_BRP_MASK)

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 */
};

#define PUCAN_TFAST_BRP_BITS		10
#define PUCAN_TFAST_TSGEG1_BITS		5
#define PUCAN_TFAST_TSGEG2_BITS		4
#define PUCAN_TFAST_SJW_BITS		4

#define PUCAN_TFAST_BRP_MASK		((1 << PUCAN_TFAST_BRP_BITS) - 1)
#define PUCAN_TFAST_TSEG1_MASK		((1 << PUCAN_TFAST_TSGEG1_BITS) - 1)
#define PUCAN_TFAST_TSEG2_MASK		((1 << PUCAN_TFAST_TSGEG2_BITS) - 1)
#define PUCAN_TFAST_SJW_MASK		((1 << PUCAN_TFAST_SJW_BITS) - 1)

/* uCAN TIMING_FAST command fields */
#define PUCAN_TFAST_SJW(s)		((s) & PUCAN_TFAST_SJW_MASK)
#define PUCAN_TFAST_TSEG2(t)		((t) & PUCAN_TFAST_TSEG2_MASK)
#define PUCAN_TFAST_TSEG1(t)		((t) & PUCAN_TFAST_TSEG1_MASK)
#define PUCAN_TFAST_BRP(b)		((b) & PUCAN_TFAST_BRP_MASK)

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 */
};

#define PUCAN_FLTSTD_ROW_IDX_MAX	((1 << PUCAN_FLTSTD_ROW_IDX_BITS) - 1)

/* uCAN SET_STD_FILTER command fields */
struct __packed pucan_std_filter {
	__le16	opcode_channel;

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

/* uCAN TX_ABORT commands fields */
#define PUCAN_TX_ABORT_FLUSH		0x0001

struct __packed pucan_tx_abort {
	__le16	opcode_channel;

	__le16	flags;
	u32	unused;
};

/* 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 SET_EN/CLR_DIS _OPTION command fields */
#define PUCAN_OPTION_ERROR		0x0001
#define PUCAN_OPTION_BUSLOAD		0x0002
#define PUCAN_OPTION_CANDFDISO		0x0004

struct __packed pucan_options {
	__le16	opcode_channel;

	__le16	options;
	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;
};

static inline int pucan_error_get_channel(const struct pucan_error_msg *msg)
{
	return msg->channel_type_d & 0x0f;
}

#define PUCAN_RX_BARRIER		0x10
#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];
};

static inline int pucan_status_get_channel(const struct pucan_status_msg *msg)
{
	return msg->channel_p_w_b & 0x0f;
}

static inline int pucan_status_is_rx_barrier(const struct pucan_status_msg *msg)
{
	return msg->channel_p_w_b & PUCAN_RX_BARRIER;
}

static inline int pucan_status_is_passive(const struct pucan_status_msg *msg)
{
	return msg->channel_p_w_b & PUCAN_BUS_PASSIVE;
}

static inline int pucan_status_is_warning(const struct pucan_status_msg *msg)
{
	return msg->channel_p_w_b & PUCAN_BUS_WARNING;
}

static inline int pucan_status_is_busoff(const struct pucan_status_msg *msg)
{
	return msg->channel_p_w_b & PUCAN_BUS_BUSOFF;
}

/* 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(int index, int opcode)
{
	return cpu_to_le16(((index) << 12) | ((opcode) & 0x3ff));
}

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

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

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

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

#endif