1 /*
2  * Copyright (c) 2019 Alexander Wachter
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <drivers/can.h>
8 #include <kernel.h>
9 #include <sys/util.h>
10 
11 #define LOG_LEVEL CONFIG_CAN_LOG_LEVEL
12 #include <logging/log.h>
13 LOG_MODULE_REGISTER(can_driver);
14 
15 #define CAN_SYNC_SEG 1
16 
17 #define WORK_BUF_COUNT_IS_POWER_OF_2 !(CONFIG_CAN_WORKQ_FRAMES_BUF_CNT & \
18 					(CONFIG_CAN_WORKQ_FRAMES_BUF_CNT - 1))
19 
20 #define WORK_BUF_MOD_MASK (CONFIG_CAN_WORKQ_FRAMES_BUF_CNT - 1)
21 
22 #if WORK_BUF_COUNT_IS_POWER_OF_2
23 #define WORK_BUF_MOD_SIZE(x) ((x) & WORK_BUF_MOD_MASK)
24 #else
25 #define WORK_BUF_MOD_SIZE(x) ((x) % CONFIG_CAN_WORKQ_FRAMES_BUF_CNT)
26 #endif
27 
28 #define WORK_BUF_FULL 0xFFFF
29 
can_msgq_put(struct zcan_frame * frame,void * arg)30 static void can_msgq_put(struct zcan_frame *frame, void *arg)
31 {
32 	struct k_msgq *msgq = (struct k_msgq *)arg;
33 	int ret;
34 
35 	__ASSERT_NO_MSG(msgq);
36 
37 	ret = k_msgq_put(msgq, frame, K_NO_WAIT);
38 	if (ret) {
39 		LOG_ERR("Msgq %p overflowed. Frame ID: 0x%x", arg, frame->id);
40 	}
41 }
42 
z_impl_can_attach_msgq(const struct device * dev,struct k_msgq * msg_q,const struct zcan_filter * filter)43 int z_impl_can_attach_msgq(const struct device *dev, struct k_msgq *msg_q,
44 			   const struct zcan_filter *filter)
45 {
46 	const struct can_driver_api *api = dev->api;
47 
48 	return api->attach_isr(dev, can_msgq_put, msg_q, filter);
49 }
50 
can_work_buffer_init(struct can_frame_buffer * buffer)51 static inline void can_work_buffer_init(struct can_frame_buffer *buffer)
52 {
53 	buffer->head = 0;
54 	buffer->tail = 0;
55 }
56 
can_work_buffer_put(struct zcan_frame * frame,struct can_frame_buffer * buffer)57 static inline int can_work_buffer_put(struct zcan_frame *frame,
58 				      struct can_frame_buffer *buffer)
59 {
60 	uint16_t next_head = WORK_BUF_MOD_SIZE(buffer->head + 1);
61 
62 	if (buffer->head == WORK_BUF_FULL) {
63 		return -1;
64 	}
65 
66 	buffer->buf[buffer->head] = *frame;
67 
68 	/* Buffer is almost full */
69 	if (next_head == buffer->tail) {
70 		buffer->head = WORK_BUF_FULL;
71 	} else {
72 		buffer->head = next_head;
73 	}
74 
75 	return 0;
76 }
77 
78 static inline
can_work_buffer_get_next(struct can_frame_buffer * buffer)79 struct zcan_frame *can_work_buffer_get_next(struct can_frame_buffer *buffer)
80 {
81 	/* Buffer empty */
82 	if (buffer->head == buffer->tail) {
83 		return NULL;
84 	} else {
85 		return &buffer->buf[buffer->tail];
86 	}
87 }
88 
can_work_buffer_free_next(struct can_frame_buffer * buffer)89 static inline void can_work_buffer_free_next(struct can_frame_buffer *buffer)
90 {
91 	uint16_t next_tail = WORK_BUF_MOD_SIZE(buffer->tail + 1);
92 
93 	if (buffer->head == buffer->tail) {
94 		return;
95 	}
96 
97 	if (buffer->head == WORK_BUF_FULL) {
98 		buffer->head = buffer->tail;
99 	}
100 
101 	buffer->tail = next_tail;
102 }
103 
can_work_handler(struct k_work * work)104 static void can_work_handler(struct k_work *work)
105 {
106 	struct zcan_work *can_work = CONTAINER_OF(work, struct zcan_work,
107 						  work_item);
108 	struct zcan_frame *frame;
109 
110 	while ((frame = can_work_buffer_get_next(&can_work->buf))) {
111 		can_work->cb(frame, can_work->cb_arg);
112 		can_work_buffer_free_next(&can_work->buf);
113 	}
114 }
115 
can_work_isr_put(struct zcan_frame * frame,void * arg)116 static void can_work_isr_put(struct zcan_frame *frame, void *arg)
117 {
118 	struct zcan_work *work = (struct zcan_work *)arg;
119 	int ret;
120 
121 	ret = can_work_buffer_put(frame, &work->buf);
122 	if (ret) {
123 		LOG_ERR("Workq buffer overflow. Msg ID: 0x%x", frame->id);
124 		return;
125 	}
126 
127 	k_work_submit_to_queue(work->work_queue, &work->work_item);
128 }
129 
can_attach_workq(const struct device * dev,struct k_work_q * work_q,struct zcan_work * work,can_rx_callback_t callback,void * callback_arg,const struct zcan_filter * filter)130 int can_attach_workq(const struct device *dev, struct k_work_q *work_q,
131 			    struct zcan_work *work,
132 			    can_rx_callback_t callback, void *callback_arg,
133 			    const struct zcan_filter *filter)
134 {
135 	const struct can_driver_api *api = dev->api;
136 
137 	k_work_init(&work->work_item, can_work_handler);
138 	work->work_queue = work_q;
139 	work->cb = callback;
140 	work->cb_arg = callback_arg;
141 	can_work_buffer_init(&work->buf);
142 
143 	return api->attach_isr(dev, can_work_isr_put, work, filter);
144 }
145 
146 
update_sampling_pnt(uint32_t ts,uint32_t sp,struct can_timing * res,const struct can_timing * max,const struct can_timing * min)147 static int update_sampling_pnt(uint32_t ts, uint32_t sp, struct can_timing *res,
148 			       const struct can_timing *max,
149 			       const struct can_timing *min)
150 {
151 	uint16_t ts1_max = max->phase_seg1 + max->prop_seg;
152 	uint16_t ts1_min = min->phase_seg1 + min->prop_seg;
153 	uint32_t sp_calc;
154 	uint16_t ts1, ts2;
155 
156 	ts2 = ts - (ts * sp) / 1000;
157 	ts2 = CLAMP(ts2, min->phase_seg2, max->phase_seg2);
158 	ts1 = ts - CAN_SYNC_SEG - ts2;
159 
160 	if (ts1 > ts1_max) {
161 		ts1 = ts1_max;
162 		ts2 = ts - CAN_SYNC_SEG - ts1;
163 		if (ts2 > max->phase_seg2) {
164 			return -1;
165 		}
166 	} else if (ts1 < ts1_min) {
167 		ts1 = ts1_min;
168 		ts2 = ts - ts1;
169 		if (ts2 < min->phase_seg2) {
170 			return -1;
171 		}
172 	}
173 
174 	res->prop_seg = CLAMP(ts1 / 2, min->prop_seg, max->prop_seg);
175 	res->phase_seg1 = ts1 - res->prop_seg;
176 	res->phase_seg2 = ts2;
177 
178 	sp_calc = (CAN_SYNC_SEG + ts1) * 1000 / ts;
179 
180 	return sp_calc > sp ? sp_calc - sp : sp - sp_calc;
181 }
182 
183 /* Internal function to do the actual calculation */
can_calc_timing_int(uint32_t core_clock,struct can_timing * res,const struct can_timing * min,const struct can_timing * max,uint32_t bitrate,uint16_t sp)184 static int can_calc_timing_int(uint32_t core_clock, struct can_timing *res,
185 			       const struct can_timing *min,
186 			       const struct can_timing *max,
187 			       uint32_t bitrate, uint16_t sp)
188 {
189 	uint32_t ts = max->prop_seg + max->phase_seg1 + max->phase_seg2 +
190 		   CAN_SYNC_SEG;
191 	uint16_t sp_err_min = UINT16_MAX;
192 	int sp_err;
193 	struct can_timing tmp_res;
194 
195 	if (sp >= 1000 ||
196 	    (!IS_ENABLED(CONFIG_CAN_FD_MODE) && bitrate > 1000000) ||
197 	     (IS_ENABLED(CONFIG_CAN_FD_MODE) && bitrate > 8000000)) {
198 		return -EINVAL;
199 	}
200 
201 	for (int prescaler = MAX(core_clock / (ts * bitrate), 1);
202 	     prescaler <= max->prescaler; ++prescaler) {
203 		if (core_clock % (prescaler * bitrate)) {
204 			/* No integer ts */
205 			continue;
206 		}
207 
208 		ts = core_clock / (prescaler * bitrate);
209 
210 		sp_err = update_sampling_pnt(ts, sp, &tmp_res,
211 					     max, min);
212 		if (sp_err < 0) {
213 			/* No prop_seg, seg1, seg2 combination possible */
214 			continue;
215 		}
216 
217 		if (sp_err < sp_err_min) {
218 			sp_err_min = sp_err;
219 			res->prop_seg = tmp_res.prop_seg;
220 			res->phase_seg1 = tmp_res.phase_seg1;
221 			res->phase_seg2 = tmp_res.phase_seg2;
222 			res->prescaler = (uint16_t)prescaler;
223 			if (sp_err == 0) {
224 				/* No better result than a perfect match*/
225 				break;
226 			}
227 		}
228 	}
229 
230 	if (sp_err_min) {
231 		LOG_DBG("SP error: %d 1/1000", sp_err_min);
232 	}
233 
234 	return sp_err_min == UINT16_MAX ? -EINVAL : (int)sp_err_min;
235 }
236 
can_calc_timing(const struct device * dev,struct can_timing * res,uint32_t bitrate,uint16_t sample_pnt)237 int can_calc_timing(const struct device *dev, struct can_timing *res,
238 		    uint32_t bitrate, uint16_t sample_pnt)
239 {
240 	const struct can_driver_api *api = dev->api;
241 	uint32_t core_clock;
242 	int ret;
243 
244 	ret = can_get_core_clock(dev, &core_clock);
245 	if (ret != 0) {
246 		return ret;
247 	}
248 
249 	return can_calc_timing_int(core_clock, res, &api->timing_min,
250 				   &api->timing_max, bitrate, sample_pnt);
251 }
252 
253 #ifdef CONFIG_CAN_FD_MODE
can_calc_timing_data(const struct device * dev,struct can_timing * res,uint32_t bitrate,uint16_t sample_pnt)254 int can_calc_timing_data(const struct device *dev, struct can_timing *res,
255 			 uint32_t bitrate, uint16_t sample_pnt)
256 {
257 	const struct can_driver_api *api = dev->api;
258 	uint32_t core_clock;
259 	int ret;
260 
261 	ret = can_get_core_clock(dev, &core_clock);
262 	if (ret != 0) {
263 		return ret;
264 	}
265 
266 	return can_calc_timing_int(core_clock, res, &api->timing_min_data,
267 				   &api->timing_max_data, bitrate, sample_pnt);
268 }
269 #endif
270 
can_calc_prescaler(const struct device * dev,struct can_timing * timing,uint32_t bitrate)271 int can_calc_prescaler(const struct device *dev, struct can_timing *timing,
272 		       uint32_t bitrate)
273 {
274 	uint32_t ts = timing->prop_seg + timing->phase_seg1 + timing->phase_seg2 +
275 		   CAN_SYNC_SEG;
276 	uint32_t core_clock;
277 	int ret;
278 
279 	ret = can_get_core_clock(dev, &core_clock);
280 	if (ret != 0) {
281 		return ret;
282 	}
283 
284 	timing->prescaler = core_clock / (bitrate * ts);
285 
286 	return core_clock % (ts * timing->prescaler);
287 }
288