1 /*
2  * Copyright (c) 2019 Alexander Wachter
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <zephyr/drivers/can.h>
8 #include <zephyr/kernel.h>
9 #include <zephyr/sys/check.h>
10 #include <zephyr/sys/util.h>
11 #include <zephyr/logging/log.h>
12 
13 LOG_MODULE_REGISTER(can_common, CONFIG_CAN_LOG_LEVEL);
14 
15 /* Maximum acceptable deviation in sample point location (permille) */
16 #define SAMPLE_POINT_MARGIN 50
17 
18 /* CAN sync segment is always one time quantum */
19 #define CAN_SYNC_SEG 1
20 
21 struct can_tx_default_cb_ctx {
22 	struct k_sem done;
23 	int status;
24 };
25 
can_tx_default_cb(const struct device * dev,int error,void * user_data)26 static void can_tx_default_cb(const struct device *dev, int error, void *user_data)
27 {
28 	struct can_tx_default_cb_ctx *ctx = user_data;
29 
30 	ctx->status = error;
31 	k_sem_give(&ctx->done);
32 }
33 
z_impl_can_send(const struct device * dev,const struct can_frame * frame,k_timeout_t timeout,can_tx_callback_t callback,void * user_data)34 int z_impl_can_send(const struct device *dev, const struct can_frame *frame,
35 		    k_timeout_t timeout, can_tx_callback_t callback,
36 		    void *user_data)
37 {
38 	const struct can_driver_api *api = (const struct can_driver_api *)dev->api;
39 	uint32_t id_mask;
40 
41 	CHECKIF(frame == NULL) {
42 		return -EINVAL;
43 	}
44 
45 	if ((frame->flags & CAN_FRAME_IDE) != 0U) {
46 		id_mask = CAN_EXT_ID_MASK;
47 	} else {
48 		id_mask = CAN_STD_ID_MASK;
49 	}
50 
51 	CHECKIF((frame->id & ~(id_mask)) != 0U) {
52 		LOG_ERR("invalid frame with %s (%d-bit) CAN ID 0x%0*x",
53 			(frame->flags & CAN_FRAME_IDE) != 0 ? "extended" : "standard",
54 			(frame->flags & CAN_FRAME_IDE) != 0 ? 29 : 11,
55 			(frame->flags & CAN_FRAME_IDE) != 0 ? 8 : 3, frame->id);
56 		return -EINVAL;
57 	}
58 
59 	if (callback == NULL) {
60 		struct can_tx_default_cb_ctx ctx;
61 		int err;
62 
63 		k_sem_init(&ctx.done, 0, 1);
64 
65 		err = api->send(dev, frame, timeout, can_tx_default_cb, &ctx);
66 		if (err != 0) {
67 			return err;
68 		}
69 
70 		k_sem_take(&ctx.done, K_FOREVER);
71 
72 		return ctx.status;
73 	}
74 
75 	return api->send(dev, frame, timeout, callback, user_data);
76 }
77 
can_add_rx_filter(const struct device * dev,can_rx_callback_t callback,void * user_data,const struct can_filter * filter)78 int can_add_rx_filter(const struct device *dev, can_rx_callback_t callback,
79 		      void *user_data, const struct can_filter *filter)
80 {
81 	const struct can_driver_api *api = (const struct can_driver_api *)dev->api;
82 	uint32_t id_mask;
83 
84 	CHECKIF(callback == NULL || filter == NULL) {
85 		return -EINVAL;
86 	}
87 
88 	if ((filter->flags & CAN_FILTER_IDE) != 0U) {
89 		id_mask = CAN_EXT_ID_MASK;
90 	} else {
91 		id_mask = CAN_STD_ID_MASK;
92 	}
93 
94 	CHECKIF(((filter->id & ~(id_mask)) != 0U) || ((filter->mask & ~(id_mask)) != 0U)) {
95 		LOG_ERR("invalid filter with %s (%d-bit) CAN ID 0x%0*x, CAN ID mask 0x%0*x",
96 			(filter->flags & CAN_FILTER_IDE) != 0 ? "extended" : "standard",
97 			(filter->flags & CAN_FILTER_IDE) != 0 ? 29 : 11,
98 			(filter->flags & CAN_FILTER_IDE) != 0 ? 8 : 3, filter->id,
99 			(filter->flags & CAN_FILTER_IDE) != 0 ? 8 : 3, filter->mask);
100 		return -EINVAL;
101 	}
102 
103 	return api->add_rx_filter(dev, callback, user_data, filter);
104 }
105 
can_msgq_put(const struct device * dev,struct can_frame * frame,void * user_data)106 static void can_msgq_put(const struct device *dev, struct can_frame *frame, void *user_data)
107 {
108 	struct k_msgq *msgq = (struct k_msgq *)user_data;
109 	int ret;
110 
111 	ARG_UNUSED(dev);
112 
113 	__ASSERT_NO_MSG(msgq);
114 
115 	ret = k_msgq_put(msgq, frame, K_NO_WAIT);
116 	if (ret) {
117 		LOG_ERR("Msgq %p overflowed. Frame ID: 0x%x", msgq, frame->id);
118 	}
119 }
120 
z_impl_can_add_rx_filter_msgq(const struct device * dev,struct k_msgq * msgq,const struct can_filter * filter)121 int z_impl_can_add_rx_filter_msgq(const struct device *dev, struct k_msgq *msgq,
122 				  const struct can_filter *filter)
123 {
124 	const struct can_driver_api *api = dev->api;
125 
126 	return api->add_rx_filter(dev, can_msgq_put, msgq, filter);
127 }
128 
129 /**
130  * @brief Update the timing given a total number of time quanta and a sample point.
131  *
132  * @code{.text}
133  *
134  * +---------------------------------------------------+
135  * |     Nominal bit time in time quanta (total_tq)    |
136  * +--------------+----------+------------+------------+
137  * |   sync_seg   | prop_seg | phase_seg1 | phase_seg2 |
138  * +--------------+----------+------------+------------+
139  * | CAN_SYNG_SEG |        tseg1          |   tseg2    |
140  * +--------------+-----------------------+------------+
141  *                                        ^
142  *                                   sample_pnt
143  * @endcode
144  *
145  * @see @a can_timing
146  *
147  * @param total_tq   Total number of time quanta.
148  * @param sample_pnt Sample point in permille of the entire bit time.
149  * @param[out] res   Result is written into the @a can_timing struct provided.
150  * @param min        Pointer to the minimum supported timing parameter values.
151  * @param max        Pointer to the maximum supported timing parameter values.
152  * @retval           0 or positive sample point error on success.
153  * @retval           -ENOTSUP if the requested sample point cannot be met.
154  */
update_sample_pnt(uint32_t total_tq,uint32_t sample_pnt,struct can_timing * res,const struct can_timing * min,const struct can_timing * max)155 static int update_sample_pnt(uint32_t total_tq, uint32_t sample_pnt, struct can_timing *res,
156 			     const struct can_timing *min, const struct can_timing *max)
157 {
158 	uint16_t tseg1_max = max->phase_seg1 + max->prop_seg;
159 	uint16_t tseg1_min = min->phase_seg1 + min->prop_seg;
160 	uint32_t sample_pnt_res;
161 	uint16_t tseg1, tseg2;
162 
163 	/* Calculate number of time quanta in tseg2 for given sample point */
164 	tseg2 = total_tq - (total_tq * sample_pnt) / 1000;
165 	tseg2 = CLAMP(tseg2, min->phase_seg2, max->phase_seg2);
166 
167 	/* Calculate number of time quanta in tseg1 */
168 	tseg1 = total_tq - CAN_SYNC_SEG - tseg2;
169 	if (tseg1 > tseg1_max) {
170 		/* Sample point location must be decreased */
171 		tseg1 = tseg1_max;
172 		tseg2 = total_tq - CAN_SYNC_SEG - tseg1;
173 
174 		if (tseg2 > max->phase_seg2) {
175 			return -ENOTSUP;
176 		}
177 	} else if (tseg1 < tseg1_min) {
178 		/* Sample point location must be increased */
179 		tseg1 = tseg1_min;
180 		tseg2 = total_tq - CAN_SYNC_SEG - tseg1;
181 
182 		if (tseg2 < min->phase_seg2) {
183 			return -ENOTSUP;
184 		}
185 	}
186 
187 	res->phase_seg2 = tseg2;
188 
189 	/* Attempt to distribute tseg1 evenly between prop_seq and phase_seg1 */
190 	res->prop_seg = CLAMP(tseg1 / 2, min->prop_seg, max->prop_seg);
191 	res->phase_seg1 = tseg1 - res->prop_seg;
192 
193 	if (res->phase_seg1 > max->phase_seg1) {
194 		/* Even tseg1 distribution not possible, decrease phase_seg1 */
195 		res->phase_seg1 = max->phase_seg1;
196 		res->prop_seg = tseg1 - res->phase_seg1;
197 	} else if (res->phase_seg1 < min->phase_seg1) {
198 		/* Even tseg1 distribution not possible, increase phase_seg1 */
199 		res->phase_seg1 = min->phase_seg1;
200 		res->prop_seg = tseg1 - res->phase_seg1;
201 	}
202 
203 	/* Calculate the resulting sample point */
204 	sample_pnt_res = (CAN_SYNC_SEG + tseg1) * 1000 / total_tq;
205 
206 	/* Return the absolute sample point error */
207 	return sample_pnt_res > sample_pnt ?
208 		sample_pnt_res - sample_pnt :
209 		sample_pnt - sample_pnt_res;
210 }
211 
212 /**
213  * @brief Get the sample point location for a given bitrate
214  *
215  * @param  bitrate The bitrate in bits/second.
216  * @return The sample point in permille.
217  */
sample_point_for_bitrate(uint32_t bitrate)218 static uint16_t sample_point_for_bitrate(uint32_t bitrate)
219 {
220 	uint16_t sample_pnt;
221 
222 	if (bitrate > 800000) {
223 		/* 75.0% */
224 		sample_pnt = 750;
225 	} else if (bitrate > 500000) {
226 		/* 80.0% */
227 		sample_pnt = 800;
228 	} else {
229 		/* 87.5% */
230 		sample_pnt = 875;
231 	}
232 
233 	return sample_pnt;
234 }
235 
236 /**
237  * @brief Internal function for calculating CAN timing parameters.
238  *
239  * @param dev        Pointer to the device structure for the driver instance.
240  * @param[out] res   Result is written into the @a can_timing struct provided.
241  * @param min        Pointer to the minimum supported timing parameter values.
242  * @param max        Pointer to the maximum supported timing parameter values.
243  * @param bitrate    Target bitrate in bits/s.
244  * @param sample_pnt Sample point in permille of the entire bit time.
245  *
246  * @retval 0 or positive sample point error on success.
247  * @retval -EINVAL if the requested bitrate or sample point is out of range.
248  * @retval -ENOTSUP if the requested bitrate is not supported.
249  * @retval -EIO if @a can_get_core_clock() is not available.
250  */
can_calc_timing_internal(const struct device * dev,struct can_timing * res,const struct can_timing * min,const struct can_timing * max,uint32_t bitrate,uint16_t sample_pnt)251 static int can_calc_timing_internal(const struct device *dev, struct can_timing *res,
252 				    const struct can_timing *min, const struct can_timing *max,
253 				    uint32_t bitrate, uint16_t sample_pnt)
254 {
255 	uint32_t total_tq = CAN_SYNC_SEG + max->prop_seg + max->phase_seg1 + max->phase_seg2;
256 	struct can_timing tmp_res = { 0 };
257 	int err_min = INT_MAX;
258 	uint32_t core_clock;
259 	int prescaler;
260 	int err;
261 
262 	if (bitrate == 0 || sample_pnt >= 1000) {
263 		return -EINVAL;
264 	}
265 
266 	err = can_get_core_clock(dev, &core_clock);
267 	if (err != 0) {
268 		return -EIO;
269 	}
270 
271 	if (sample_pnt == 0U) {
272 		sample_pnt = sample_point_for_bitrate(bitrate);
273 	}
274 
275 	for (prescaler = MAX(core_clock / (total_tq * bitrate), min->prescaler);
276 	     prescaler <= max->prescaler;
277 	     prescaler++) {
278 
279 		if (core_clock % (prescaler * bitrate)) {
280 			/* No integer total_tq for this prescaler setting */
281 			continue;
282 		}
283 
284 		total_tq = core_clock / (prescaler * bitrate);
285 
286 		err = update_sample_pnt(total_tq, sample_pnt, &tmp_res, min, max);
287 		if (err < 0) {
288 			/* Sample point cannot be met for this prescaler setting */
289 			continue;
290 		}
291 
292 		if (err < err_min) {
293 			/* Improved sample point match */
294 			err_min = err;
295 			res->prop_seg = tmp_res.prop_seg;
296 			res->phase_seg1 = tmp_res.phase_seg1;
297 			res->phase_seg2 = tmp_res.phase_seg2;
298 			res->prescaler = (uint16_t)prescaler;
299 
300 			if (err == 0) {
301 				/* Perfect sample point match */
302 				break;
303 			}
304 		}
305 	}
306 
307 	if (err_min != 0U) {
308 		LOG_DBG("Sample point error: %d 1/1000", err_min);
309 	}
310 
311 	/* Calculate default sjw as phase_seg2 / 2 and clamp the result */
312 	res->sjw = MIN(res->phase_seg1, res->phase_seg2 / 2);
313 	res->sjw = CLAMP(res->sjw, min->sjw, max->sjw);
314 
315 	return err_min == INT_MAX ? -ENOTSUP : err_min;
316 }
317 
z_impl_can_calc_timing(const struct device * dev,struct can_timing * res,uint32_t bitrate,uint16_t sample_pnt)318 int z_impl_can_calc_timing(const struct device *dev, struct can_timing *res,
319 			   uint32_t bitrate, uint16_t sample_pnt)
320 {
321 	const struct can_timing *min = can_get_timing_min(dev);
322 	const struct can_timing *max = can_get_timing_max(dev);
323 
324 	if (bitrate > 1000000) {
325 		return -EINVAL;
326 	}
327 
328 	return can_calc_timing_internal(dev, res, min, max, bitrate, sample_pnt);
329 }
330 
331 #ifdef CONFIG_CAN_FD_MODE
z_impl_can_calc_timing_data(const struct device * dev,struct can_timing * res,uint32_t bitrate,uint16_t sample_pnt)332 int z_impl_can_calc_timing_data(const struct device *dev, struct can_timing *res,
333 				uint32_t bitrate, uint16_t sample_pnt)
334 {
335 	const struct can_timing *min = can_get_timing_data_min(dev);
336 	const struct can_timing *max = can_get_timing_data_max(dev);
337 
338 	if (bitrate > 8000000) {
339 		return -EINVAL;
340 	}
341 
342 	return can_calc_timing_internal(dev, res, min, max, bitrate, sample_pnt);
343 }
344 #endif /* CONFIG_CAN_FD_MODE */
345 
can_calc_prescaler(const struct device * dev,struct can_timing * timing,uint32_t bitrate)346 int can_calc_prescaler(const struct device *dev, struct can_timing *timing,
347 		       uint32_t bitrate)
348 {
349 	uint32_t ts = timing->prop_seg + timing->phase_seg1 + timing->phase_seg2 +
350 		   CAN_SYNC_SEG;
351 	uint32_t core_clock;
352 	int ret;
353 
354 	ret = can_get_core_clock(dev, &core_clock);
355 	if (ret != 0) {
356 		return ret;
357 	}
358 
359 	timing->prescaler = core_clock / (bitrate * ts);
360 
361 	return core_clock % (ts * timing->prescaler);
362 }
363 
check_timing_in_range(const struct can_timing * timing,const struct can_timing * min,const struct can_timing * max)364 static int check_timing_in_range(const struct can_timing *timing,
365 				 const struct can_timing *min,
366 				 const struct can_timing *max)
367 {
368 	if (!IN_RANGE(timing->sjw, min->sjw, max->sjw) ||
369 	    !IN_RANGE(timing->prop_seg, min->prop_seg, max->prop_seg) ||
370 	    !IN_RANGE(timing->phase_seg1, min->phase_seg1, max->phase_seg1) ||
371 	    !IN_RANGE(timing->phase_seg2, min->phase_seg2, max->phase_seg2) ||
372 	    !IN_RANGE(timing->prescaler, min->prescaler, max->prescaler)) {
373 		return -ENOTSUP;
374 	}
375 
376 	if ((timing->sjw > timing->phase_seg1) || (timing->sjw > timing->phase_seg2)) {
377 		return -ENOTSUP;
378 	}
379 
380 	return 0;
381 }
382 
z_impl_can_set_timing(const struct device * dev,const struct can_timing * timing)383 int z_impl_can_set_timing(const struct device *dev,
384 			  const struct can_timing *timing)
385 {
386 	const struct can_driver_api *api = (const struct can_driver_api *)dev->api;
387 	const struct can_timing *min = can_get_timing_min(dev);
388 	const struct can_timing *max = can_get_timing_max(dev);
389 	int err;
390 
391 	err = check_timing_in_range(timing, min, max);
392 	if (err != 0) {
393 		return err;
394 	}
395 
396 	return api->set_timing(dev, timing);
397 }
398 
z_impl_can_set_bitrate(const struct device * dev,uint32_t bitrate)399 int z_impl_can_set_bitrate(const struct device *dev, uint32_t bitrate)
400 {
401 	struct can_timing timing = { 0 };
402 	uint32_t min = can_get_bitrate_min(dev);
403 	uint32_t max = can_get_bitrate_max(dev);
404 	uint16_t sample_pnt;
405 	int ret;
406 
407 	if ((bitrate < min) || (bitrate > max)) {
408 		return -ENOTSUP;
409 	}
410 
411 	sample_pnt = sample_point_for_bitrate(bitrate);
412 	ret = can_calc_timing(dev, &timing, bitrate, sample_pnt);
413 	if (ret < 0) {
414 		return ret;
415 	}
416 
417 	if (ret > SAMPLE_POINT_MARGIN) {
418 		return -ERANGE;
419 	}
420 
421 	return can_set_timing(dev, &timing);
422 }
423 
424 #ifdef CONFIG_CAN_FD_MODE
z_impl_can_set_timing_data(const struct device * dev,const struct can_timing * timing_data)425 int z_impl_can_set_timing_data(const struct device *dev,
426 			       const struct can_timing *timing_data)
427 {
428 	const struct can_driver_api *api = (const struct can_driver_api *)dev->api;
429 	const struct can_timing *min = can_get_timing_data_min(dev);
430 	const struct can_timing *max = can_get_timing_data_max(dev);
431 	int err;
432 
433 	if (api->set_timing_data == NULL) {
434 		return -ENOSYS;
435 	}
436 
437 	err = check_timing_in_range(timing_data, min, max);
438 	if (err != 0) {
439 		return err;
440 	}
441 
442 	return api->set_timing_data(dev, timing_data);
443 }
444 
z_impl_can_set_bitrate_data(const struct device * dev,uint32_t bitrate_data)445 int z_impl_can_set_bitrate_data(const struct device *dev, uint32_t bitrate_data)
446 {
447 	struct can_timing timing_data = { 0 };
448 	uint32_t min = can_get_bitrate_min(dev);
449 	uint32_t max = can_get_bitrate_max(dev);
450 	uint16_t sample_pnt;
451 	int ret;
452 
453 	if ((bitrate_data < min) || (bitrate_data > max)) {
454 		return -ENOTSUP;
455 	}
456 
457 	sample_pnt = sample_point_for_bitrate(bitrate_data);
458 	ret = can_calc_timing_data(dev, &timing_data, bitrate_data, sample_pnt);
459 	if (ret < 0) {
460 		return ret;
461 	}
462 
463 	if (ret > SAMPLE_POINT_MARGIN) {
464 		return -ERANGE;
465 	}
466 
467 	return can_set_timing_data(dev, &timing_data);
468 }
469 #endif /* CONFIG_CAN_FD_MODE */
470