1 | /* SPDX-License-Identifier: GPL-2.0-only */ |
2 | /* |
3 | * CAN driver for PEAK System micro-CAN based adapters |
4 | * |
5 | * Copyright (C) 2003-2011 PEAK System-Technik GmbH |
6 | * Copyright (C) 2011-2013 Stephane Grosjean <s.grosjean@peak-system.com> |
7 | */ |
8 | #ifndef PUCAN_H |
9 | #define PUCAN_H |
10 | |
11 | /* uCAN commands opcodes list (low-order 10 bits) */ |
12 | #define PUCAN_CMD_NOP 0x000 |
13 | #define PUCAN_CMD_RESET_MODE 0x001 |
14 | #define PUCAN_CMD_NORMAL_MODE 0x002 |
15 | #define PUCAN_CMD_LISTEN_ONLY_MODE 0x003 |
16 | #define PUCAN_CMD_TIMING_SLOW 0x004 |
17 | #define PUCAN_CMD_TIMING_FAST 0x005 |
18 | #define PUCAN_CMD_SET_STD_FILTER 0x006 |
19 | #define PUCAN_CMD_RESERVED2 0x007 |
20 | #define PUCAN_CMD_FILTER_STD 0x008 |
21 | #define PUCAN_CMD_TX_ABORT 0x009 |
22 | #define PUCAN_CMD_WR_ERR_CNT 0x00a |
23 | #define PUCAN_CMD_SET_EN_OPTION 0x00b |
24 | #define PUCAN_CMD_CLR_DIS_OPTION 0x00c |
25 | #define PUCAN_CMD_RX_BARRIER 0x010 |
26 | #define PUCAN_CMD_END_OF_COLLECTION 0x3ff |
27 | |
28 | /* uCAN received messages list */ |
29 | #define PUCAN_MSG_CAN_RX 0x0001 |
30 | #define PUCAN_MSG_ERROR 0x0002 |
31 | #define PUCAN_MSG_STATUS 0x0003 |
32 | #define PUCAN_MSG_BUSLOAD 0x0004 |
33 | |
34 | #define PUCAN_MSG_CACHE_CRITICAL 0x0102 |
35 | |
36 | /* uCAN transmitted messages */ |
37 | #define PUCAN_MSG_CAN_TX 0x1000 |
38 | |
39 | /* uCAN command common header */ |
40 | struct __packed pucan_command { |
41 | __le16 opcode_channel; |
42 | u16 args[3]; |
43 | }; |
44 | |
45 | /* return the opcode from the opcode_channel field of a command */ |
46 | static inline u16 pucan_cmd_get_opcode(struct pucan_command *c) |
47 | { |
48 | return le16_to_cpu(c->opcode_channel) & 0x3ff; |
49 | } |
50 | |
51 | #define PUCAN_TSLOW_BRP_BITS 10 |
52 | #define PUCAN_TSLOW_TSGEG1_BITS 8 |
53 | #define PUCAN_TSLOW_TSGEG2_BITS 7 |
54 | #define PUCAN_TSLOW_SJW_BITS 7 |
55 | |
56 | #define PUCAN_TSLOW_BRP_MASK ((1 << PUCAN_TSLOW_BRP_BITS) - 1) |
57 | #define PUCAN_TSLOW_TSEG1_MASK ((1 << PUCAN_TSLOW_TSGEG1_BITS) - 1) |
58 | #define PUCAN_TSLOW_TSEG2_MASK ((1 << PUCAN_TSLOW_TSGEG2_BITS) - 1) |
59 | #define PUCAN_TSLOW_SJW_MASK ((1 << PUCAN_TSLOW_SJW_BITS) - 1) |
60 | |
61 | /* uCAN TIMING_SLOW command fields */ |
62 | #define PUCAN_TSLOW_SJW_T(s, t) (((s) & PUCAN_TSLOW_SJW_MASK) | \ |
63 | ((!!(t)) << 7)) |
64 | #define PUCAN_TSLOW_TSEG2(t) ((t) & PUCAN_TSLOW_TSEG2_MASK) |
65 | #define PUCAN_TSLOW_TSEG1(t) ((t) & PUCAN_TSLOW_TSEG1_MASK) |
66 | #define PUCAN_TSLOW_BRP(b) ((b) & PUCAN_TSLOW_BRP_MASK) |
67 | |
68 | struct __packed pucan_timing_slow { |
69 | __le16 opcode_channel; |
70 | |
71 | u8 ewl; /* Error Warning limit */ |
72 | u8 sjw_t; /* Sync Jump Width + Triple sampling */ |
73 | u8 tseg2; /* Timing SEGment 2 */ |
74 | u8 tseg1; /* Timing SEGment 1 */ |
75 | |
76 | __le16 brp; /* BaudRate Prescaler */ |
77 | }; |
78 | |
79 | #define PUCAN_TFAST_BRP_BITS 10 |
80 | #define PUCAN_TFAST_TSGEG1_BITS 5 |
81 | #define PUCAN_TFAST_TSGEG2_BITS 4 |
82 | #define PUCAN_TFAST_SJW_BITS 4 |
83 | |
84 | #define PUCAN_TFAST_BRP_MASK ((1 << PUCAN_TFAST_BRP_BITS) - 1) |
85 | #define PUCAN_TFAST_TSEG1_MASK ((1 << PUCAN_TFAST_TSGEG1_BITS) - 1) |
86 | #define PUCAN_TFAST_TSEG2_MASK ((1 << PUCAN_TFAST_TSGEG2_BITS) - 1) |
87 | #define PUCAN_TFAST_SJW_MASK ((1 << PUCAN_TFAST_SJW_BITS) - 1) |
88 | |
89 | /* uCAN TIMING_FAST command fields */ |
90 | #define PUCAN_TFAST_SJW(s) ((s) & PUCAN_TFAST_SJW_MASK) |
91 | #define PUCAN_TFAST_TSEG2(t) ((t) & PUCAN_TFAST_TSEG2_MASK) |
92 | #define PUCAN_TFAST_TSEG1(t) ((t) & PUCAN_TFAST_TSEG1_MASK) |
93 | #define PUCAN_TFAST_BRP(b) ((b) & PUCAN_TFAST_BRP_MASK) |
94 | |
95 | struct __packed pucan_timing_fast { |
96 | __le16 opcode_channel; |
97 | |
98 | u8 unused; |
99 | u8 sjw; /* Sync Jump Width */ |
100 | u8 tseg2; /* Timing SEGment 2 */ |
101 | u8 tseg1; /* Timing SEGment 1 */ |
102 | |
103 | __le16 brp; /* BaudRate Prescaler */ |
104 | }; |
105 | |
106 | /* uCAN FILTER_STD command fields */ |
107 | #define PUCAN_FLTSTD_ROW_IDX_BITS 6 |
108 | |
109 | struct __packed pucan_filter_std { |
110 | __le16 opcode_channel; |
111 | |
112 | __le16 idx; |
113 | __le32 mask; /* CAN-ID bitmask in idx range */ |
114 | }; |
115 | |
116 | #define PUCAN_FLTSTD_ROW_IDX_MAX ((1 << PUCAN_FLTSTD_ROW_IDX_BITS) - 1) |
117 | |
118 | /* uCAN SET_STD_FILTER command fields */ |
119 | struct __packed pucan_std_filter { |
120 | __le16 opcode_channel; |
121 | |
122 | u8 unused; |
123 | u8 idx; |
124 | __le32 mask; /* CAN-ID bitmask in idx range */ |
125 | }; |
126 | |
127 | /* uCAN TX_ABORT commands fields */ |
128 | #define PUCAN_TX_ABORT_FLUSH 0x0001 |
129 | |
130 | struct __packed pucan_tx_abort { |
131 | __le16 opcode_channel; |
132 | |
133 | __le16 flags; |
134 | u32 unused; |
135 | }; |
136 | |
137 | /* uCAN WR_ERR_CNT command fields */ |
138 | #define PUCAN_WRERRCNT_TE 0x4000 /* Tx error cntr write Enable */ |
139 | #define PUCAN_WRERRCNT_RE 0x8000 /* Rx error cntr write Enable */ |
140 | |
141 | struct __packed pucan_wr_err_cnt { |
142 | __le16 opcode_channel; |
143 | |
144 | __le16 sel_mask; |
145 | u8 tx_counter; /* Tx error counter new value */ |
146 | u8 rx_counter; /* Rx error counter new value */ |
147 | |
148 | u16 unused; |
149 | }; |
150 | |
151 | /* uCAN SET_EN/CLR_DIS _OPTION command fields */ |
152 | #define PUCAN_OPTION_ERROR 0x0001 |
153 | #define PUCAN_OPTION_BUSLOAD 0x0002 |
154 | #define PUCAN_OPTION_CANDFDISO 0x0004 |
155 | |
156 | struct __packed pucan_options { |
157 | __le16 opcode_channel; |
158 | |
159 | __le16 options; |
160 | u32 unused; |
161 | }; |
162 | |
163 | /* uCAN received messages global format */ |
164 | struct __packed pucan_msg { |
165 | __le16 size; |
166 | __le16 type; |
167 | __le32 ts_low; |
168 | __le32 ts_high; |
169 | }; |
170 | |
171 | /* uCAN flags for CAN/CANFD messages */ |
172 | #define PUCAN_MSG_SELF_RECEIVE 0x80 |
173 | #define PUCAN_MSG_ERROR_STATE_IND 0x40 /* error state indicator */ |
174 | #define PUCAN_MSG_BITRATE_SWITCH 0x20 /* bitrate switch */ |
175 | #define PUCAN_MSG_EXT_DATA_LEN 0x10 /* extended data length */ |
176 | #define PUCAN_MSG_SINGLE_SHOT 0x08 |
177 | #define PUCAN_MSG_LOOPED_BACK 0x04 |
178 | #define PUCAN_MSG_EXT_ID 0x02 |
179 | #define PUCAN_MSG_RTR 0x01 |
180 | |
181 | struct __packed pucan_rx_msg { |
182 | __le16 size; |
183 | __le16 type; |
184 | __le32 ts_low; |
185 | __le32 ts_high; |
186 | __le32 tag_low; |
187 | __le32 tag_high; |
188 | u8 channel_dlc; |
189 | u8 client; |
190 | __le16 flags; |
191 | __le32 can_id; |
192 | u8 d[]; |
193 | }; |
194 | |
195 | /* uCAN error types */ |
196 | #define PUCAN_ERMSG_BIT_ERROR 0 |
197 | #define PUCAN_ERMSG_FORM_ERROR 1 |
198 | #define PUCAN_ERMSG_STUFF_ERROR 2 |
199 | #define PUCAN_ERMSG_OTHER_ERROR 3 |
200 | #define PUCAN_ERMSG_ERR_CNT_DEC 4 |
201 | |
202 | struct __packed pucan_error_msg { |
203 | __le16 size; |
204 | __le16 type; |
205 | __le32 ts_low; |
206 | __le32 ts_high; |
207 | u8 channel_type_d; |
208 | u8 code_g; |
209 | u8 tx_err_cnt; |
210 | u8 rx_err_cnt; |
211 | }; |
212 | |
213 | static inline int pucan_error_get_channel(const struct pucan_error_msg *msg) |
214 | { |
215 | return msg->channel_type_d & 0x0f; |
216 | } |
217 | |
218 | #define PUCAN_RX_BARRIER 0x10 |
219 | #define PUCAN_BUS_PASSIVE 0x20 |
220 | #define PUCAN_BUS_WARNING 0x40 |
221 | #define PUCAN_BUS_BUSOFF 0x80 |
222 | |
223 | struct __packed pucan_status_msg { |
224 | __le16 size; |
225 | __le16 type; |
226 | __le32 ts_low; |
227 | __le32 ts_high; |
228 | u8 channel_p_w_b; |
229 | u8 unused[3]; |
230 | }; |
231 | |
232 | static inline int pucan_status_get_channel(const struct pucan_status_msg *msg) |
233 | { |
234 | return msg->channel_p_w_b & 0x0f; |
235 | } |
236 | |
237 | static inline int pucan_status_is_rx_barrier(const struct pucan_status_msg *msg) |
238 | { |
239 | return msg->channel_p_w_b & PUCAN_RX_BARRIER; |
240 | } |
241 | |
242 | static inline int pucan_status_is_passive(const struct pucan_status_msg *msg) |
243 | { |
244 | return msg->channel_p_w_b & PUCAN_BUS_PASSIVE; |
245 | } |
246 | |
247 | static inline int pucan_status_is_warning(const struct pucan_status_msg *msg) |
248 | { |
249 | return msg->channel_p_w_b & PUCAN_BUS_WARNING; |
250 | } |
251 | |
252 | static inline int pucan_status_is_busoff(const struct pucan_status_msg *msg) |
253 | { |
254 | return msg->channel_p_w_b & PUCAN_BUS_BUSOFF; |
255 | } |
256 | |
257 | /* uCAN transmitted message format */ |
258 | #define PUCAN_MSG_CHANNEL_DLC(c, d) (((c) & 0xf) | ((d) << 4)) |
259 | |
260 | struct __packed pucan_tx_msg { |
261 | __le16 size; |
262 | __le16 type; |
263 | __le32 tag_low; |
264 | __le32 tag_high; |
265 | u8 channel_dlc; |
266 | u8 client; |
267 | __le16 flags; |
268 | __le32 can_id; |
269 | u8 d[]; |
270 | }; |
271 | |
272 | /* build the cmd opcode_channel field with respect to the correct endianness */ |
273 | static inline __le16 pucan_cmd_opcode_channel(int index, int opcode) |
274 | { |
275 | return cpu_to_le16(((index) << 12) | ((opcode) & 0x3ff)); |
276 | } |
277 | |
278 | /* return the channel number part from any received message channel_dlc field */ |
279 | static inline int pucan_msg_get_channel(const struct pucan_rx_msg *msg) |
280 | { |
281 | return msg->channel_dlc & 0xf; |
282 | } |
283 | |
284 | /* return the dlc value from any received message channel_dlc field */ |
285 | static inline u8 pucan_msg_get_dlc(const struct pucan_rx_msg *msg) |
286 | { |
287 | return msg->channel_dlc >> 4; |
288 | } |
289 | |
290 | static inline int pucan_ermsg_get_channel(const struct pucan_error_msg *msg) |
291 | { |
292 | return msg->channel_type_d & 0x0f; |
293 | } |
294 | |
295 | static inline int pucan_stmsg_get_channel(const struct pucan_status_msg *msg) |
296 | { |
297 | return msg->channel_p_w_b & 0x0f; |
298 | } |
299 | |
300 | #endif |
301 | |