blob: 5fd627e9da19859f28c3de93446c3c4e367c269c (
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
|
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* 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>
*/
#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[];
};
/* 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[];
};
/* 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
|