1 /*
2 * Copyright (c) 2018 Karsten Koenig
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #define DT_DRV_COMPAT microchip_mcp2515
8
9 #include <zephyr/kernel.h>
10 #include <zephyr/device.h>
11 #include <zephyr/drivers/can/transceiver.h>
12 #include <zephyr/drivers/spi.h>
13 #include <zephyr/drivers/gpio.h>
14 #include <zephyr/logging/log.h>
15
16 LOG_MODULE_REGISTER(can_mcp2515, CONFIG_CAN_LOG_LEVEL);
17
18 #include "can_mcp2515.h"
19
20 /* Timeout for changing mode */
21 #define MCP2515_MODE_CHANGE_TIMEOUT_USEC 1000
22 #define MCP2515_MODE_CHANGE_RETRIES 100
23 #define MCP2515_MODE_CHANGE_DELAY \
24 K_USEC(MCP2515_MODE_CHANGE_TIMEOUT_USEC / MCP2515_MODE_CHANGE_RETRIES)
25
mcp2515_cmd_soft_reset(const struct device * dev)26 static int mcp2515_cmd_soft_reset(const struct device *dev)
27 {
28 const struct mcp2515_config *dev_cfg = dev->config;
29
30 uint8_t cmd_buf[] = { MCP2515_OPCODE_RESET };
31
32 const struct spi_buf tx_buf = {
33 .buf = cmd_buf, .len = sizeof(cmd_buf),
34 };
35 const struct spi_buf_set tx = {
36 .buffers = &tx_buf, .count = 1U
37 };
38
39 return spi_write_dt(&dev_cfg->bus, &tx);
40 }
41
mcp2515_cmd_bit_modify(const struct device * dev,uint8_t reg_addr,uint8_t mask,uint8_t data)42 static int mcp2515_cmd_bit_modify(const struct device *dev, uint8_t reg_addr,
43 uint8_t mask,
44 uint8_t data)
45 {
46 const struct mcp2515_config *dev_cfg = dev->config;
47
48 uint8_t cmd_buf[] = { MCP2515_OPCODE_BIT_MODIFY, reg_addr, mask, data };
49
50 const struct spi_buf tx_buf = {
51 .buf = cmd_buf, .len = sizeof(cmd_buf),
52 };
53 const struct spi_buf_set tx = {
54 .buffers = &tx_buf, .count = 1U
55 };
56
57 return spi_write_dt(&dev_cfg->bus, &tx);
58 }
59
mcp2515_cmd_write_reg(const struct device * dev,uint8_t reg_addr,uint8_t * buf_data,uint8_t buf_len)60 static int mcp2515_cmd_write_reg(const struct device *dev, uint8_t reg_addr,
61 uint8_t *buf_data, uint8_t buf_len)
62 {
63 const struct mcp2515_config *dev_cfg = dev->config;
64
65 uint8_t cmd_buf[] = { MCP2515_OPCODE_WRITE, reg_addr };
66
67 struct spi_buf tx_buf[] = {
68 { .buf = cmd_buf, .len = sizeof(cmd_buf) },
69 { .buf = buf_data, .len = buf_len }
70 };
71 const struct spi_buf_set tx = {
72 .buffers = tx_buf, .count = ARRAY_SIZE(tx_buf)
73 };
74
75 return spi_write_dt(&dev_cfg->bus, &tx);
76 }
77
78 /*
79 * Load TX buffer instruction
80 *
81 * When loading a transmit buffer, reduces the overhead of a normal WRITE
82 * command by placing the Address Pointer at one of six locations, as
83 * selected by parameter abc.
84 *
85 * 0: TX Buffer 0, Start at TXB0SIDH (0x31)
86 * 1: TX Buffer 0, Start at TXB0D0 (0x36)
87 * 2: TX Buffer 1, Start at TXB1SIDH (0x41)
88 * 3: TX Buffer 1, Start at TXB1D0 (0x46)
89 * 4: TX Buffer 2, Start at TXB2SIDH (0x51)
90 * 5: TX Buffer 2, Start at TXB2D0 (0x56)
91 */
mcp2515_cmd_load_tx_buffer(const struct device * dev,uint8_t abc,uint8_t * buf_data,uint8_t buf_len)92 static int mcp2515_cmd_load_tx_buffer(const struct device *dev, uint8_t abc,
93 uint8_t *buf_data, uint8_t buf_len)
94 {
95 const struct mcp2515_config *dev_cfg = dev->config;
96
97 __ASSERT(abc <= 5, "abc <= 5");
98
99 uint8_t cmd_buf[] = { MCP2515_OPCODE_LOAD_TX_BUFFER | abc };
100
101 struct spi_buf tx_buf[] = {
102 { .buf = cmd_buf, .len = sizeof(cmd_buf) },
103 { .buf = buf_data, .len = buf_len }
104 };
105 const struct spi_buf_set tx = {
106 .buffers = tx_buf, .count = ARRAY_SIZE(tx_buf)
107 };
108
109 return spi_write_dt(&dev_cfg->bus, &tx);
110 }
111
112 /*
113 * Request-to-Send Instruction
114 *
115 * Parameter nnn is the combination of bits at positions 0, 1 and 2 in the RTS
116 * opcode that respectively initiate transmission for buffers TXB0, TXB1 and
117 * TXB2.
118 */
mcp2515_cmd_rts(const struct device * dev,uint8_t nnn)119 static int mcp2515_cmd_rts(const struct device *dev, uint8_t nnn)
120 {
121 const struct mcp2515_config *dev_cfg = dev->config;
122
123 __ASSERT(nnn < BIT(MCP2515_TX_CNT), "nnn < BIT(MCP2515_TX_CNT)");
124
125 uint8_t cmd_buf[] = { MCP2515_OPCODE_RTS | nnn };
126
127 struct spi_buf tx_buf[] = {
128 { .buf = cmd_buf, .len = sizeof(cmd_buf) }
129 };
130 const struct spi_buf_set tx = {
131 .buffers = tx_buf, .count = ARRAY_SIZE(tx_buf)
132 };
133
134 return spi_write_dt(&dev_cfg->bus, &tx);
135 }
136
mcp2515_cmd_read_reg(const struct device * dev,uint8_t reg_addr,uint8_t * buf_data,uint8_t buf_len)137 static int mcp2515_cmd_read_reg(const struct device *dev, uint8_t reg_addr,
138 uint8_t *buf_data, uint8_t buf_len)
139 {
140 const struct mcp2515_config *dev_cfg = dev->config;
141
142 uint8_t cmd_buf[] = { MCP2515_OPCODE_READ, reg_addr };
143
144 struct spi_buf tx_buf[] = {
145 { .buf = cmd_buf, .len = sizeof(cmd_buf) },
146 { .buf = NULL, .len = buf_len }
147 };
148 const struct spi_buf_set tx = {
149 .buffers = tx_buf, .count = ARRAY_SIZE(tx_buf)
150 };
151 struct spi_buf rx_buf[] = {
152 { .buf = NULL, .len = sizeof(cmd_buf) },
153 { .buf = buf_data, .len = buf_len }
154 };
155 const struct spi_buf_set rx = {
156 .buffers = rx_buf, .count = ARRAY_SIZE(rx_buf)
157 };
158
159 return spi_transceive_dt(&dev_cfg->bus, &tx, &rx);
160 }
161
162 /*
163 * Read RX Buffer instruction
164 *
165 * When reading a receive buffer, reduces the overhead of a normal READ
166 * command by placing the Address Pointer at one of four locations selected by
167 * parameter nm:
168 * 0: Receive Buffer 0, Start at RXB0SIDH (0x61)
169 * 1: Receive Buffer 0, Start at RXB0D0 (0x66)
170 * 2: Receive Buffer 1, Start at RXB1SIDH (0x71)
171 * 3: Receive Buffer 1, Start at RXB1D0 (0x76)
172 */
mcp2515_cmd_read_rx_buffer(const struct device * dev,uint8_t nm,uint8_t * buf_data,uint8_t buf_len)173 static int mcp2515_cmd_read_rx_buffer(const struct device *dev, uint8_t nm,
174 uint8_t *buf_data, uint8_t buf_len)
175 {
176 const struct mcp2515_config *dev_cfg = dev->config;
177
178 __ASSERT(nm <= 0x03, "nm <= 0x03");
179
180 uint8_t cmd_buf[] = { MCP2515_OPCODE_READ_RX_BUFFER | (nm << 1) };
181
182 struct spi_buf tx_buf[] = {
183 { .buf = cmd_buf, .len = sizeof(cmd_buf) },
184 { .buf = NULL, .len = buf_len }
185 };
186 const struct spi_buf_set tx = {
187 .buffers = tx_buf, .count = ARRAY_SIZE(tx_buf)
188 };
189 struct spi_buf rx_buf[] = {
190 { .buf = NULL, .len = sizeof(cmd_buf) },
191 { .buf = buf_data, .len = buf_len }
192 };
193 const struct spi_buf_set rx = {
194 .buffers = rx_buf, .count = ARRAY_SIZE(rx_buf)
195 };
196
197 return spi_transceive_dt(&dev_cfg->bus, &tx, &rx);
198 }
199
mcp2515_convert_canframe_to_mcp2515frame(const struct can_frame * source,uint8_t * target)200 static void mcp2515_convert_canframe_to_mcp2515frame(const struct can_frame
201 *source, uint8_t *target)
202 {
203 uint8_t rtr;
204 uint8_t dlc;
205 uint8_t data_idx;
206
207 if ((source->flags & CAN_FRAME_IDE) != 0) {
208 target[MCP2515_FRAME_OFFSET_SIDH] = source->id >> 21;
209 target[MCP2515_FRAME_OFFSET_SIDL] =
210 (((source->id >> 18) & 0x07) << 5) | (BIT(3)) |
211 ((source->id >> 16) & 0x03);
212 target[MCP2515_FRAME_OFFSET_EID8] = source->id >> 8;
213 target[MCP2515_FRAME_OFFSET_EID0] = source->id;
214 } else {
215 target[MCP2515_FRAME_OFFSET_SIDH] = source->id >> 3;
216 target[MCP2515_FRAME_OFFSET_SIDL] =
217 (source->id & 0x07) << 5;
218 }
219
220 rtr = (source->flags & CAN_FRAME_RTR) != 0 ? BIT(6) : 0;
221 dlc = (source->dlc) & 0x0F;
222
223 target[MCP2515_FRAME_OFFSET_DLC] = rtr | dlc;
224
225 if (rtr == 0U) {
226 for (data_idx = 0U; data_idx < dlc; data_idx++) {
227 target[MCP2515_FRAME_OFFSET_D0 + data_idx] =
228 source->data[data_idx];
229 }
230 }
231 }
232
mcp2515_convert_mcp2515frame_to_canframe(const uint8_t * source,struct can_frame * target)233 static void mcp2515_convert_mcp2515frame_to_canframe(const uint8_t *source,
234 struct can_frame *target)
235 {
236 uint8_t data_idx;
237
238 memset(target, 0, sizeof(*target));
239
240 if (source[MCP2515_FRAME_OFFSET_SIDL] & BIT(3)) {
241 target->flags |= CAN_FRAME_IDE;
242 target->id =
243 (source[MCP2515_FRAME_OFFSET_SIDH] << 21) |
244 ((source[MCP2515_FRAME_OFFSET_SIDL] >> 5) << 18) |
245 ((source[MCP2515_FRAME_OFFSET_SIDL] & 0x03) << 16) |
246 (source[MCP2515_FRAME_OFFSET_EID8] << 8) |
247 source[MCP2515_FRAME_OFFSET_EID0];
248 } else {
249 target->id = (source[MCP2515_FRAME_OFFSET_SIDH] << 3) |
250 (source[MCP2515_FRAME_OFFSET_SIDL] >> 5);
251 }
252
253 target->dlc = source[MCP2515_FRAME_OFFSET_DLC] & 0x0F;
254
255 if ((source[MCP2515_FRAME_OFFSET_DLC] & BIT(6)) != 0) {
256 target->flags |= CAN_FRAME_RTR;
257 } else {
258 for (data_idx = 0U; data_idx < target->dlc; data_idx++) {
259 target->data[data_idx] = source[MCP2515_FRAME_OFFSET_D0 +
260 data_idx];
261 }
262 }
263 }
264
mcp2515_set_mode_int(const struct device * dev,uint8_t mcp2515_mode)265 const int mcp2515_set_mode_int(const struct device *dev, uint8_t mcp2515_mode)
266 {
267 int retries = MCP2515_MODE_CHANGE_RETRIES;
268 uint8_t canstat;
269
270 mcp2515_cmd_bit_modify(dev, MCP2515_ADDR_CANCTRL,
271 MCP2515_CANCTRL_MODE_MASK,
272 mcp2515_mode << MCP2515_CANCTRL_MODE_POS);
273 mcp2515_cmd_read_reg(dev, MCP2515_ADDR_CANSTAT, &canstat, 1);
274
275 while (((canstat & MCP2515_CANSTAT_MODE_MASK) >> MCP2515_CANSTAT_MODE_POS)
276 != mcp2515_mode) {
277 if (--retries < 0) {
278 LOG_ERR("Timeout trying to set MCP2515 operation mode");
279 return -EIO;
280 }
281
282 k_sleep(MCP2515_MODE_CHANGE_DELAY);
283 mcp2515_cmd_read_reg(dev, MCP2515_ADDR_CANSTAT, &canstat, 1);
284 }
285
286 return 0;
287 }
288
mcp2515_tx_done(const struct device * dev,uint8_t tx_idx,int status)289 static void mcp2515_tx_done(const struct device *dev, uint8_t tx_idx, int status)
290 {
291 struct mcp2515_data *dev_data = dev->data;
292 can_tx_callback_t callback = dev_data->tx_cb[tx_idx].cb;
293
294 if (callback != NULL) {
295 callback(dev, status, dev_data->tx_cb[tx_idx].cb_arg);
296 dev_data->tx_cb[tx_idx].cb = NULL;
297
298 k_mutex_lock(&dev_data->mutex, K_FOREVER);
299 dev_data->tx_busy_map &= ~BIT(tx_idx);
300 k_mutex_unlock(&dev_data->mutex);
301 k_sem_give(&dev_data->tx_sem);
302 }
303 }
304
mcp2515_get_core_clock(const struct device * dev,uint32_t * rate)305 static int mcp2515_get_core_clock(const struct device *dev, uint32_t *rate)
306 {
307 const struct mcp2515_config *dev_cfg = dev->config;
308
309 *rate = dev_cfg->osc_freq / 2;
310 return 0;
311 }
312
mcp2515_get_max_filters(const struct device * dev,bool ide)313 static int mcp2515_get_max_filters(const struct device *dev, bool ide)
314 {
315 ARG_UNUSED(ide);
316
317 return CONFIG_CAN_MAX_FILTER;
318 }
319
mcp2515_set_timing(const struct device * dev,const struct can_timing * timing)320 static int mcp2515_set_timing(const struct device *dev,
321 const struct can_timing *timing)
322 {
323 struct mcp2515_data *dev_data = dev->data;
324 int ret;
325
326 if (!timing) {
327 return -EINVAL;
328 }
329
330 if (dev_data->common.started) {
331 return -EBUSY;
332 }
333
334 /* CNF3, CNF2, CNF1, CANINTE */
335 uint8_t config_buf[4];
336
337 /* CNF1; SJW<7:6> | BRP<5:0> */
338 __ASSERT(timing->prescaler > 0, "Prescaler should be bigger than zero");
339 uint8_t brp = timing->prescaler - 1;
340 uint8_t sjw = (timing->sjw - 1) << 6;
341 uint8_t cnf1 = sjw | brp;
342
343 /* CNF2; BTLMODE<7>|SAM<6>|PHSEG1<5:3>|PRSEG<2:0> */
344 const uint8_t btlmode = 1 << 7;
345 const uint8_t sam = 0 << 6;
346 const uint8_t phseg1 = (timing->phase_seg1 - 1) << 3;
347 const uint8_t prseg = (timing->prop_seg - 1);
348
349 const uint8_t cnf2 = btlmode | sam | phseg1 | prseg;
350
351 /* CNF3; SOF<7>|WAKFIL<6>|UND<5:3>|PHSEG2<2:0> */
352 const uint8_t sof = 0 << 7;
353 const uint8_t wakfil = 0 << 6;
354 const uint8_t und = 0 << 3;
355 const uint8_t phseg2 = (timing->phase_seg2 - 1);
356
357 const uint8_t cnf3 = sof | wakfil | und | phseg2;
358
359 const uint8_t caninte = MCP2515_INTE_RX0IE | MCP2515_INTE_RX1IE |
360 MCP2515_INTE_TX0IE | MCP2515_INTE_TX1IE |
361 MCP2515_INTE_TX2IE | MCP2515_INTE_ERRIE;
362
363 /* Receive everything, filtering done in driver, RXB0 roll over into
364 * RXB1 */
365 const uint8_t rx0_ctrl = BIT(6) | BIT(5) | BIT(2);
366 const uint8_t rx1_ctrl = BIT(6) | BIT(5);
367
368 config_buf[0] = cnf3;
369 config_buf[1] = cnf2;
370 config_buf[2] = cnf1;
371 config_buf[3] = caninte;
372
373 k_mutex_lock(&dev_data->mutex, K_FOREVER);
374
375 ret = mcp2515_cmd_write_reg(dev, MCP2515_ADDR_CNF3, config_buf,
376 sizeof(config_buf));
377 if (ret < 0) {
378 LOG_ERR("Failed to write the configuration [%d]", ret);
379 goto done;
380 }
381
382 ret = mcp2515_cmd_bit_modify(dev, MCP2515_ADDR_RXB0CTRL, rx0_ctrl,
383 rx0_ctrl);
384 if (ret < 0) {
385 LOG_ERR("Failed to write RXB0CTRL [%d]", ret);
386 goto done;
387 }
388
389 ret = mcp2515_cmd_bit_modify(dev, MCP2515_ADDR_RXB1CTRL, rx1_ctrl,
390 rx1_ctrl);
391 if (ret < 0) {
392 LOG_ERR("Failed to write RXB1CTRL [%d]", ret);
393 goto done;
394 }
395
396 done:
397 k_mutex_unlock(&dev_data->mutex);
398 return ret;
399 }
400
mcp2515_get_capabilities(const struct device * dev,can_mode_t * cap)401 static int mcp2515_get_capabilities(const struct device *dev, can_mode_t *cap)
402 {
403 ARG_UNUSED(dev);
404
405 *cap = CAN_MODE_NORMAL | CAN_MODE_LISTENONLY | CAN_MODE_LOOPBACK;
406
407 return 0;
408 }
409
mcp2515_start(const struct device * dev)410 static int mcp2515_start(const struct device *dev)
411 {
412 const struct mcp2515_config *dev_cfg = dev->config;
413 struct mcp2515_data *dev_data = dev->data;
414 int ret;
415
416 if (dev_data->common.started) {
417 return -EALREADY;
418 }
419
420 if (dev_cfg->common.phy != NULL) {
421 ret = can_transceiver_enable(dev_cfg->common.phy, dev_data->common.mode);
422 if (ret != 0) {
423 LOG_ERR("Failed to enable CAN transceiver [%d]", ret);
424 return ret;
425 }
426 }
427
428 CAN_STATS_RESET(dev);
429
430 k_mutex_lock(&dev_data->mutex, K_FOREVER);
431
432 ret = mcp2515_set_mode_int(dev, dev_data->mcp2515_mode);
433 if (ret < 0) {
434 LOG_ERR("Failed to set the mode [%d]", ret);
435
436 if (dev_cfg->common.phy != NULL) {
437 /* Attempt to disable the CAN transceiver in case of error */
438 (void)can_transceiver_disable(dev_cfg->common.phy);
439 }
440 } else {
441 dev_data->common.started = true;
442 }
443
444 k_mutex_unlock(&dev_data->mutex);
445
446 return ret;
447 }
448
mcp2515_stop(const struct device * dev)449 static int mcp2515_stop(const struct device *dev)
450 {
451 const struct mcp2515_config *dev_cfg = dev->config;
452 struct mcp2515_data *dev_data = dev->data;
453 int ret;
454 int i;
455
456 if (!dev_data->common.started) {
457 return -EALREADY;
458 }
459
460 k_mutex_lock(&dev_data->mutex, K_FOREVER);
461
462 /* Abort any pending transmissions before entering configuration mode */
463 mcp2515_cmd_bit_modify(dev, MCP2515_ADDR_TXB0CTRL,
464 MCP2515_TXBNCTRL_TXREQ_MASK, 0);
465 #if MCP2515_TX_CNT == 2
466 mcp2515_cmd_bit_modify(dev, MCP2515_ADDR_TXB1CTRL,
467 MCP2515_TXBNCTRL_TXREQ_MASK, 0);
468 #endif /* MCP2515_TX_CNT == 2 */
469 #if MCP2515_TX_CNT == 3
470 mcp2515_cmd_bit_modify(dev, MCP2515_ADDR_TXB2CTRL,
471 MCP2515_TXBNCTRL_TXREQ_MASK, 0);
472 #endif /* MCP2515_TX_CNT == 3 */
473
474 ret = mcp2515_set_mode_int(dev, MCP2515_MODE_CONFIGURATION);
475 if (ret < 0) {
476 LOG_ERR("Failed to enter configuration mode [%d]", ret);
477 k_mutex_unlock(&dev_data->mutex);
478 return ret;
479 }
480
481 dev_data->common.started = false;
482
483 k_mutex_unlock(&dev_data->mutex);
484
485 for (i = 0; i < MCP2515_TX_CNT; i++) {
486 mcp2515_tx_done(dev, i, -ENETDOWN);
487 }
488
489 if (dev_cfg->common.phy != NULL) {
490 ret = can_transceiver_disable(dev_cfg->common.phy);
491 if (ret != 0) {
492 LOG_ERR("Failed to disable CAN transceiver [%d]", ret);
493 return ret;
494 }
495 }
496
497 return 0;
498 }
499
mcp2515_set_mode(const struct device * dev,can_mode_t mode)500 static int mcp2515_set_mode(const struct device *dev, can_mode_t mode)
501 {
502 struct mcp2515_data *dev_data = dev->data;
503
504 if (dev_data->common.started) {
505 return -EBUSY;
506 }
507
508 switch (mode) {
509 case CAN_MODE_NORMAL:
510 dev_data->mcp2515_mode = MCP2515_MODE_NORMAL;
511 break;
512 case CAN_MODE_LISTENONLY:
513 dev_data->mcp2515_mode = MCP2515_MODE_SILENT;
514 break;
515 case CAN_MODE_LOOPBACK:
516 dev_data->mcp2515_mode = MCP2515_MODE_LOOPBACK;
517 break;
518 default:
519 LOG_ERR("Unsupported CAN Mode %u", mode);
520 return -ENOTSUP;
521 }
522
523 dev_data->common.mode = mode;
524
525 return 0;
526 }
527
mcp2515_send(const struct device * dev,const struct can_frame * frame,k_timeout_t timeout,can_tx_callback_t callback,void * user_data)528 static int mcp2515_send(const struct device *dev,
529 const struct can_frame *frame,
530 k_timeout_t timeout, can_tx_callback_t callback,
531 void *user_data)
532 {
533 struct mcp2515_data *dev_data = dev->data;
534 uint8_t tx_idx = 0U;
535 uint8_t abc;
536 uint8_t nnn;
537 uint8_t len;
538 uint8_t tx_frame[MCP2515_FRAME_LEN];
539
540 if (frame->dlc > CAN_MAX_DLC) {
541 LOG_ERR("DLC of %d exceeds maximum (%d)",
542 frame->dlc, CAN_MAX_DLC);
543 return -EINVAL;
544 }
545
546 if ((frame->flags & ~(CAN_FRAME_IDE | CAN_FRAME_RTR)) != 0) {
547 LOG_ERR("unsupported CAN frame flags 0x%02x", frame->flags);
548 return -ENOTSUP;
549 }
550
551 if (!dev_data->common.started) {
552 return -ENETDOWN;
553 }
554
555 if (k_sem_take(&dev_data->tx_sem, timeout) != 0) {
556 return -EAGAIN;
557 }
558
559 k_mutex_lock(&dev_data->mutex, K_FOREVER);
560
561 /* find a free tx slot */
562 for (; tx_idx < MCP2515_TX_CNT; tx_idx++) {
563 if ((BIT(tx_idx) & dev_data->tx_busy_map) == 0) {
564 dev_data->tx_busy_map |= BIT(tx_idx);
565 break;
566 }
567 }
568
569 k_mutex_unlock(&dev_data->mutex);
570
571 if (tx_idx == MCP2515_TX_CNT) {
572 LOG_WRN("no free tx slot available");
573 return -EIO;
574 }
575
576 dev_data->tx_cb[tx_idx].cb = callback;
577 dev_data->tx_cb[tx_idx].cb_arg = user_data;
578
579 mcp2515_convert_canframe_to_mcp2515frame(frame, tx_frame);
580
581 /* Address Pointer selection */
582 abc = 2 * tx_idx;
583
584 /* Calculate minimum length to transfer */
585 len = sizeof(tx_frame) - CAN_MAX_DLC + frame->dlc;
586
587 mcp2515_cmd_load_tx_buffer(dev, abc, tx_frame, len);
588
589 /* request tx slot transmission */
590 nnn = BIT(tx_idx);
591 mcp2515_cmd_rts(dev, nnn);
592
593 return 0;
594 }
595
mcp2515_add_rx_filter(const struct device * dev,can_rx_callback_t rx_cb,void * cb_arg,const struct can_filter * filter)596 static int mcp2515_add_rx_filter(const struct device *dev,
597 can_rx_callback_t rx_cb,
598 void *cb_arg,
599 const struct can_filter *filter)
600 {
601 struct mcp2515_data *dev_data = dev->data;
602 int filter_id = 0;
603
604 __ASSERT(rx_cb != NULL, "response_ptr can not be null");
605
606 if ((filter->flags & ~(CAN_FILTER_IDE)) != 0) {
607 LOG_ERR("unsupported CAN filter flags 0x%02x", filter->flags);
608 return -ENOTSUP;
609 }
610
611 k_mutex_lock(&dev_data->mutex, K_FOREVER);
612
613 /* find free filter */
614 while ((BIT(filter_id) & dev_data->filter_usage)
615 && (filter_id < CONFIG_CAN_MAX_FILTER)) {
616 filter_id++;
617 }
618
619 /* setup filter */
620 if (filter_id < CONFIG_CAN_MAX_FILTER) {
621 dev_data->filter_usage |= BIT(filter_id);
622
623 dev_data->filter[filter_id] = *filter;
624 dev_data->rx_cb[filter_id] = rx_cb;
625 dev_data->cb_arg[filter_id] = cb_arg;
626
627 } else {
628 filter_id = -ENOSPC;
629 }
630
631 k_mutex_unlock(&dev_data->mutex);
632
633 return filter_id;
634 }
635
mcp2515_remove_rx_filter(const struct device * dev,int filter_id)636 static void mcp2515_remove_rx_filter(const struct device *dev, int filter_id)
637 {
638 struct mcp2515_data *dev_data = dev->data;
639
640 if (filter_id < 0 || filter_id >= CONFIG_CAN_MAX_FILTER) {
641 LOG_ERR("filter ID %d out of bounds", filter_id);
642 return;
643 }
644
645 k_mutex_lock(&dev_data->mutex, K_FOREVER);
646 dev_data->filter_usage &= ~BIT(filter_id);
647 k_mutex_unlock(&dev_data->mutex);
648 }
649
mcp2515_set_state_change_callback(const struct device * dev,can_state_change_callback_t cb,void * user_data)650 static void mcp2515_set_state_change_callback(const struct device *dev,
651 can_state_change_callback_t cb,
652 void *user_data)
653 {
654 struct mcp2515_data *dev_data = dev->data;
655
656 dev_data->common.state_change_cb = cb;
657 dev_data->common.state_change_cb_user_data = user_data;
658 }
659
mcp2515_rx_filter(const struct device * dev,struct can_frame * frame)660 static void mcp2515_rx_filter(const struct device *dev,
661 struct can_frame *frame)
662 {
663 struct mcp2515_data *dev_data = dev->data;
664 uint8_t filter_id = 0U;
665 can_rx_callback_t callback;
666 struct can_frame tmp_frame;
667
668 #ifndef CONFIG_CAN_ACCEPT_RTR
669 if ((frame->flags & CAN_FRAME_RTR) != 0U) {
670 return;
671 }
672 #endif /* !CONFIG_CAN_ACCEPT_RTR */
673
674 k_mutex_lock(&dev_data->mutex, K_FOREVER);
675
676 for (; filter_id < CONFIG_CAN_MAX_FILTER; filter_id++) {
677 if (!(BIT(filter_id) & dev_data->filter_usage)) {
678 continue; /* filter slot empty */
679 }
680
681 if (!can_frame_matches_filter(frame, &dev_data->filter[filter_id])) {
682 continue; /* filter did not match */
683 }
684
685 callback = dev_data->rx_cb[filter_id];
686 /*Make a temporary copy in case the user modifies the message*/
687 tmp_frame = *frame;
688
689 callback(dev, &tmp_frame, dev_data->cb_arg[filter_id]);
690 }
691
692 k_mutex_unlock(&dev_data->mutex);
693 }
694
mcp2515_rx(const struct device * dev,uint8_t rx_idx)695 static void mcp2515_rx(const struct device *dev, uint8_t rx_idx)
696 {
697 __ASSERT(rx_idx < MCP2515_RX_CNT, "rx_idx < MCP2515_RX_CNT");
698
699 struct can_frame frame;
700 uint8_t rx_frame[MCP2515_FRAME_LEN];
701 uint8_t nm;
702
703 /* Address Pointer selection */
704 nm = 2 * rx_idx;
705
706 /* Fetch rx buffer */
707 mcp2515_cmd_read_rx_buffer(dev, nm, rx_frame, sizeof(rx_frame));
708 mcp2515_convert_mcp2515frame_to_canframe(rx_frame, &frame);
709 mcp2515_rx_filter(dev, &frame);
710 }
711
mcp2515_get_state(const struct device * dev,enum can_state * state,struct can_bus_err_cnt * err_cnt)712 static int mcp2515_get_state(const struct device *dev, enum can_state *state,
713 struct can_bus_err_cnt *err_cnt)
714 {
715 struct mcp2515_data *dev_data = dev->data;
716 uint8_t eflg;
717 uint8_t err_cnt_buf[2];
718 int ret;
719
720 ret = mcp2515_cmd_read_reg(dev, MCP2515_ADDR_EFLG, &eflg, sizeof(eflg));
721 if (ret < 0) {
722 LOG_ERR("Failed to read error register [%d]", ret);
723 return -EIO;
724 }
725
726 if (state != NULL) {
727 if (!dev_data->common.started) {
728 *state = CAN_STATE_STOPPED;
729 } else if (eflg & MCP2515_EFLG_TXBO) {
730 *state = CAN_STATE_BUS_OFF;
731 } else if ((eflg & MCP2515_EFLG_RXEP) || (eflg & MCP2515_EFLG_TXEP)) {
732 *state = CAN_STATE_ERROR_PASSIVE;
733 } else if (eflg & MCP2515_EFLG_EWARN) {
734 *state = CAN_STATE_ERROR_WARNING;
735 } else {
736 *state = CAN_STATE_ERROR_ACTIVE;
737 }
738 }
739
740 if (err_cnt != NULL) {
741 ret = mcp2515_cmd_read_reg(dev, MCP2515_ADDR_TEC, err_cnt_buf,
742 sizeof(err_cnt_buf));
743 if (ret < 0) {
744 LOG_ERR("Failed to read error counters [%d]", ret);
745 return -EIO;
746 }
747
748 err_cnt->tx_err_cnt = err_cnt_buf[0];
749 err_cnt->rx_err_cnt = err_cnt_buf[1];
750 }
751
752 #ifdef CONFIG_CAN_STATS
753 if ((eflg & (MCP2515_EFLG_RX0OVR | MCP2515_EFLG_RX1OVR)) != 0U) {
754 CAN_STATS_RX_OVERRUN_INC(dev);
755
756 ret = mcp2515_cmd_bit_modify(dev, MCP2515_ADDR_EFLG,
757 eflg & (MCP2515_EFLG_RX0OVR | MCP2515_EFLG_RX1OVR),
758 0U);
759 if (ret < 0) {
760 LOG_ERR("Failed to clear RX overrun flags [%d]", ret);
761 return -EIO;
762 }
763 }
764 #endif /* CONFIG_CAN_STATS */
765
766 return 0;
767 }
768
mcp2515_handle_errors(const struct device * dev)769 static void mcp2515_handle_errors(const struct device *dev)
770 {
771 struct mcp2515_data *dev_data = dev->data;
772 can_state_change_callback_t state_change_cb = dev_data->common.state_change_cb;
773 void *state_change_cb_data = dev_data->common.state_change_cb_user_data;
774 enum can_state state;
775 struct can_bus_err_cnt err_cnt;
776 int err;
777
778 err = mcp2515_get_state(dev, &state, state_change_cb ? &err_cnt : NULL);
779 if (err != 0) {
780 LOG_ERR("Failed to get CAN controller state [%d]", err);
781 return;
782 }
783
784 if (state_change_cb && dev_data->old_state != state) {
785 dev_data->old_state = state;
786 state_change_cb(dev, state, err_cnt, state_change_cb_data);
787 }
788 }
789
mcp2515_handle_interrupts(const struct device * dev)790 static void mcp2515_handle_interrupts(const struct device *dev)
791 {
792 const struct mcp2515_config *dev_cfg = dev->config;
793 int ret;
794 uint8_t canintf;
795
796 /* Loop until INT pin is inactive (all interrupt flags handled) */
797 while (1) {
798 ret = mcp2515_cmd_read_reg(dev, MCP2515_ADDR_CANINTF,
799 &canintf, 1);
800 if (ret != 0) {
801 LOG_ERR("Couldn't read INTF register %d", ret);
802 continue;
803 }
804
805 if (canintf == 0) {
806 /* No interrupt flags set */
807 break;
808 }
809
810 if (canintf & MCP2515_CANINTF_RX0IF) {
811 mcp2515_rx(dev, 0);
812
813 /* RX0IF flag cleared automatically during read */
814 canintf &= ~MCP2515_CANINTF_RX0IF;
815 }
816
817 if (canintf & MCP2515_CANINTF_RX1IF) {
818 mcp2515_rx(dev, 1);
819
820 /* RX1IF flag cleared automatically during read */
821 canintf &= ~MCP2515_CANINTF_RX1IF;
822 }
823
824 if (canintf & MCP2515_CANINTF_TX0IF) {
825 mcp2515_tx_done(dev, 0, 0);
826 }
827
828 if (canintf & MCP2515_CANINTF_TX1IF) {
829 mcp2515_tx_done(dev, 1, 0);
830 }
831
832 if (canintf & MCP2515_CANINTF_TX2IF) {
833 mcp2515_tx_done(dev, 2, 0);
834 }
835
836 if (canintf & MCP2515_CANINTF_ERRIF) {
837 mcp2515_handle_errors(dev);
838 }
839
840 if (canintf != 0) {
841 /* Clear remaining flags */
842 mcp2515_cmd_bit_modify(dev, MCP2515_ADDR_CANINTF,
843 canintf, ~canintf);
844 }
845
846 /* Break from loop if INT pin is inactive */
847 ret = gpio_pin_get_dt(&dev_cfg->int_gpio);
848 if (ret < 0) {
849 LOG_ERR("Couldn't read INT pin");
850 } else if (ret == 0) {
851 /* All interrupt flags handled */
852 break;
853 }
854 }
855 }
856
mcp2515_int_thread(void * p1,void * p2,void * p3)857 static void mcp2515_int_thread(void *p1, void *p2, void *p3)
858 {
859 ARG_UNUSED(p2);
860 ARG_UNUSED(p3);
861
862 const struct device *dev = p1;
863 struct mcp2515_data *dev_data = dev->data;
864
865 while (1) {
866 k_sem_take(&dev_data->int_sem, K_FOREVER);
867 mcp2515_handle_interrupts(dev);
868 }
869 }
870
mcp2515_int_gpio_callback(const struct device * dev,struct gpio_callback * cb,uint32_t pins)871 static void mcp2515_int_gpio_callback(const struct device *dev,
872 struct gpio_callback *cb, uint32_t pins)
873 {
874 struct mcp2515_data *dev_data =
875 CONTAINER_OF(cb, struct mcp2515_data, int_gpio_cb);
876
877 k_sem_give(&dev_data->int_sem);
878 }
879
880 static const struct can_driver_api can_api_funcs = {
881 .get_capabilities = mcp2515_get_capabilities,
882 .set_timing = mcp2515_set_timing,
883 .start = mcp2515_start,
884 .stop = mcp2515_stop,
885 .set_mode = mcp2515_set_mode,
886 .send = mcp2515_send,
887 .add_rx_filter = mcp2515_add_rx_filter,
888 .remove_rx_filter = mcp2515_remove_rx_filter,
889 .get_state = mcp2515_get_state,
890 .set_state_change_callback = mcp2515_set_state_change_callback,
891 .get_core_clock = mcp2515_get_core_clock,
892 .get_max_filters = mcp2515_get_max_filters,
893 .timing_min = {
894 .sjw = 0x1,
895 .prop_seg = 0x01,
896 .phase_seg1 = 0x01,
897 .phase_seg2 = 0x02,
898 .prescaler = 0x01
899 },
900 .timing_max = {
901 .sjw = 0x04,
902 .prop_seg = 0x08,
903 .phase_seg1 = 0x08,
904 .phase_seg2 = 0x08,
905 .prescaler = 0x40
906 }
907 };
908
909
mcp2515_init(const struct device * dev)910 static int mcp2515_init(const struct device *dev)
911 {
912 const struct mcp2515_config *dev_cfg = dev->config;
913 struct mcp2515_data *dev_data = dev->data;
914 struct can_timing timing = { 0 };
915 k_tid_t tid;
916 int ret;
917
918 k_sem_init(&dev_data->int_sem, 0, 1);
919 k_mutex_init(&dev_data->mutex);
920 k_sem_init(&dev_data->tx_sem, MCP2515_TX_CNT, MCP2515_TX_CNT);
921
922 if (dev_cfg->common.phy != NULL) {
923 if (!device_is_ready(dev_cfg->common.phy)) {
924 LOG_ERR("CAN transceiver not ready");
925 return -ENODEV;
926 }
927 }
928
929 if (!spi_is_ready_dt(&dev_cfg->bus)) {
930 LOG_ERR("SPI bus %s not ready", dev_cfg->bus.bus->name);
931 return -ENODEV;
932 }
933
934 /* Reset MCP2515 */
935 if (mcp2515_cmd_soft_reset(dev)) {
936 LOG_ERR("Soft-reset failed");
937 return -EIO;
938 }
939
940 /* Initialize interrupt handling */
941 if (!gpio_is_ready_dt(&dev_cfg->int_gpio)) {
942 LOG_ERR("Interrupt GPIO port not ready");
943 return -ENODEV;
944 }
945
946 if (gpio_pin_configure_dt(&dev_cfg->int_gpio, GPIO_INPUT)) {
947 LOG_ERR("Unable to configure interrupt GPIO");
948 return -EINVAL;
949 }
950
951 gpio_init_callback(&(dev_data->int_gpio_cb), mcp2515_int_gpio_callback,
952 BIT(dev_cfg->int_gpio.pin));
953
954 if (gpio_add_callback(dev_cfg->int_gpio.port,
955 &(dev_data->int_gpio_cb))) {
956 return -EINVAL;
957 }
958
959 if (gpio_pin_interrupt_configure_dt(&dev_cfg->int_gpio,
960 GPIO_INT_EDGE_TO_ACTIVE)) {
961 return -EINVAL;
962 }
963
964 tid = k_thread_create(&dev_data->int_thread, dev_data->int_thread_stack,
965 dev_cfg->int_thread_stack_size,
966 mcp2515_int_thread, (void *)dev,
967 NULL, NULL, K_PRIO_COOP(dev_cfg->int_thread_priority),
968 0, K_NO_WAIT);
969 (void)k_thread_name_set(tid, "mcp2515");
970
971 (void)memset(dev_data->rx_cb, 0, sizeof(dev_data->rx_cb));
972 (void)memset(dev_data->filter, 0, sizeof(dev_data->filter));
973 dev_data->old_state = CAN_STATE_ERROR_ACTIVE;
974
975 ret = can_calc_timing(dev, &timing, dev_cfg->common.bitrate,
976 dev_cfg->common.sample_point);
977 if (ret == -EINVAL) {
978 LOG_ERR("Can't find timing for given param");
979 return -EIO;
980 }
981
982 LOG_DBG("Presc: %d, BS1: %d, BS2: %d",
983 timing.prescaler, timing.phase_seg1, timing.phase_seg2);
984 LOG_DBG("Sample-point err : %d", ret);
985
986 k_usleep(MCP2515_OSC_STARTUP_US);
987
988 ret = can_set_timing(dev, &timing);
989 if (ret) {
990 return ret;
991 }
992
993 ret = can_set_mode(dev, CAN_MODE_NORMAL);
994
995 return ret;
996 }
997
998 #define MCP2515_INIT(inst) \
999 static K_KERNEL_STACK_DEFINE(mcp2515_int_thread_stack_##inst, \
1000 CONFIG_CAN_MCP2515_INT_THREAD_STACK_SIZE); \
1001 \
1002 static struct mcp2515_data mcp2515_data_##inst = { \
1003 .int_thread_stack = mcp2515_int_thread_stack_##inst, \
1004 .tx_busy_map = 0U, \
1005 .filter_usage = 0U, \
1006 }; \
1007 \
1008 static const struct mcp2515_config mcp2515_config_##inst = { \
1009 .common = CAN_DT_DRIVER_CONFIG_INST_GET(inst, 0, 1000000), \
1010 .bus = SPI_DT_SPEC_INST_GET(inst, SPI_WORD_SET(8), 0), \
1011 .int_gpio = GPIO_DT_SPEC_INST_GET(inst, int_gpios), \
1012 .int_thread_stack_size = CONFIG_CAN_MCP2515_INT_THREAD_STACK_SIZE, \
1013 .int_thread_priority = CONFIG_CAN_MCP2515_INT_THREAD_PRIO, \
1014 .osc_freq = DT_INST_PROP(inst, osc_freq), \
1015 }; \
1016 \
1017 CAN_DEVICE_DT_INST_DEFINE(inst, mcp2515_init, NULL, &mcp2515_data_##inst, \
1018 &mcp2515_config_##inst, POST_KERNEL, CONFIG_CAN_INIT_PRIORITY, \
1019 &can_api_funcs);
1020
1021 DT_INST_FOREACH_STATUS_OKAY(MCP2515_INIT)
1022