1 /*
2  * Copyright (c) 2022 Intel Corporation
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <string.h>
8 
9 #include <zephyr/toolchain.h>
10 #include <zephyr/sys/__assert.h>
11 
12 #include <zephyr/drivers/i3c.h>
13 
14 #include <zephyr/logging/log.h>
15 LOG_MODULE_DECLARE(i3c, CONFIG_I3C_LOG_LEVEL);
16 
i3c_ccc_do_getbcr(struct i3c_device_desc * target,struct i3c_ccc_getbcr * bcr)17 int i3c_ccc_do_getbcr(struct i3c_device_desc *target,
18 		      struct i3c_ccc_getbcr *bcr)
19 {
20 	struct i3c_ccc_payload ccc_payload;
21 	struct i3c_ccc_target_payload ccc_tgt_payload;
22 
23 	__ASSERT_NO_MSG(target != NULL);
24 	__ASSERT_NO_MSG(target->bus != NULL);
25 	__ASSERT_NO_MSG(bcr != NULL);
26 
27 	ccc_tgt_payload.addr = target->dynamic_addr;
28 	ccc_tgt_payload.rnw = 1;
29 	ccc_tgt_payload.data = &bcr->bcr;
30 	ccc_tgt_payload.data_len = sizeof(bcr->bcr);
31 
32 	memset(&ccc_payload, 0, sizeof(ccc_payload));
33 	ccc_payload.ccc.id = I3C_CCC_GETBCR;
34 	ccc_payload.targets.payloads = &ccc_tgt_payload;
35 	ccc_payload.targets.num_targets = 1;
36 
37 	return i3c_do_ccc(target->bus, &ccc_payload);
38 }
39 
i3c_ccc_do_getdcr(struct i3c_device_desc * target,struct i3c_ccc_getdcr * dcr)40 int i3c_ccc_do_getdcr(struct i3c_device_desc *target,
41 		      struct i3c_ccc_getdcr *dcr)
42 {
43 	struct i3c_ccc_payload ccc_payload;
44 	struct i3c_ccc_target_payload ccc_tgt_payload;
45 
46 	__ASSERT_NO_MSG(target != NULL);
47 	__ASSERT_NO_MSG(target->bus != NULL);
48 	__ASSERT_NO_MSG(dcr != NULL);
49 
50 	ccc_tgt_payload.addr = target->dynamic_addr;
51 	ccc_tgt_payload.rnw = 1;
52 	ccc_tgt_payload.data = &dcr->dcr;
53 	ccc_tgt_payload.data_len = sizeof(dcr->dcr);
54 
55 	memset(&ccc_payload, 0, sizeof(ccc_payload));
56 	ccc_payload.ccc.id = I3C_CCC_GETDCR;
57 	ccc_payload.targets.payloads = &ccc_tgt_payload;
58 	ccc_payload.targets.num_targets = 1;
59 
60 	return i3c_do_ccc(target->bus, &ccc_payload);
61 }
62 
i3c_ccc_do_getpid(struct i3c_device_desc * target,struct i3c_ccc_getpid * pid)63 int i3c_ccc_do_getpid(struct i3c_device_desc *target,
64 		      struct i3c_ccc_getpid *pid)
65 {
66 	struct i3c_ccc_payload ccc_payload;
67 	struct i3c_ccc_target_payload ccc_tgt_payload;
68 
69 	__ASSERT_NO_MSG(target != NULL);
70 	__ASSERT_NO_MSG(target->bus != NULL);
71 	__ASSERT_NO_MSG(pid != NULL);
72 
73 	ccc_tgt_payload.addr = target->dynamic_addr;
74 	ccc_tgt_payload.rnw = 1;
75 	ccc_tgt_payload.data = &pid->pid[0];
76 	ccc_tgt_payload.data_len = sizeof(pid->pid);
77 
78 	memset(&ccc_payload, 0, sizeof(ccc_payload));
79 	ccc_payload.ccc.id = I3C_CCC_GETPID;
80 	ccc_payload.targets.payloads = &ccc_tgt_payload;
81 	ccc_payload.targets.num_targets = 1;
82 
83 	return i3c_do_ccc(target->bus, &ccc_payload);
84 }
85 
i3c_ccc_do_rstact_all(const struct device * controller,enum i3c_ccc_rstact_defining_byte action)86 int i3c_ccc_do_rstact_all(const struct device *controller,
87 			  enum i3c_ccc_rstact_defining_byte action)
88 {
89 	struct i3c_ccc_payload ccc_payload;
90 	uint8_t def_byte;
91 
92 	__ASSERT_NO_MSG(controller != NULL);
93 
94 	memset(&ccc_payload, 0, sizeof(ccc_payload));
95 	ccc_payload.ccc.id = I3C_CCC_RSTACT(true);
96 
97 	def_byte = (uint8_t)action;
98 	ccc_payload.ccc.data = &def_byte;
99 	ccc_payload.ccc.data_len = 1U;
100 
101 	return i3c_do_ccc(controller, &ccc_payload);
102 }
103 
i3c_ccc_do_rstdaa_all(const struct device * controller)104 int i3c_ccc_do_rstdaa_all(const struct device *controller)
105 {
106 	struct i3c_ccc_payload ccc_payload;
107 
108 	__ASSERT_NO_MSG(controller != NULL);
109 
110 	memset(&ccc_payload, 0, sizeof(ccc_payload));
111 	ccc_payload.ccc.id = I3C_CCC_RSTDAA;
112 
113 	return i3c_do_ccc(controller, &ccc_payload);
114 }
115 
i3c_ccc_do_setdasa(const struct i3c_device_desc * target)116 int i3c_ccc_do_setdasa(const struct i3c_device_desc *target)
117 {
118 	struct i3c_driver_data *bus_data = (struct i3c_driver_data *)target->bus->data;
119 	struct i3c_ccc_payload ccc_payload;
120 	struct i3c_ccc_target_payload ccc_tgt_payload;
121 	uint8_t dyn_addr;
122 
123 	__ASSERT_NO_MSG(target != NULL);
124 	__ASSERT_NO_MSG(target->bus != NULL);
125 
126 	if ((target->static_addr == 0U) || (target->dynamic_addr != 0U)) {
127 		return -EINVAL;
128 	}
129 
130 	/*
131 	 * Note that the 7-bit address needs to start at bit 1
132 	 * (aka left-justified). So shift left by 1;
133 	 */
134 	dyn_addr = (target->init_dynamic_addr ?
135 				target->init_dynamic_addr : target->static_addr) << 1;
136 
137 	/* check that initial dynamic address is free before setting it */
138 	if ((target->init_dynamic_addr != 0) &&
139 		(target->init_dynamic_addr != target->static_addr)) {
140 		if (!i3c_addr_slots_is_free(&bus_data->attached_dev.addr_slots, dyn_addr >> 1)) {
141 			return -EINVAL;
142 		}
143 	}
144 
145 	ccc_tgt_payload.addr = target->static_addr;
146 	ccc_tgt_payload.rnw = 0;
147 	ccc_tgt_payload.data = &dyn_addr;
148 	ccc_tgt_payload.data_len = 1;
149 
150 	memset(&ccc_payload, 0, sizeof(ccc_payload));
151 	ccc_payload.ccc.id = I3C_CCC_SETDASA;
152 	ccc_payload.targets.payloads = &ccc_tgt_payload;
153 	ccc_payload.targets.num_targets = 1;
154 
155 	return i3c_do_ccc(target->bus, &ccc_payload);
156 }
157 
i3c_ccc_do_setnewda(const struct i3c_device_desc * target,struct i3c_ccc_address new_da)158 int i3c_ccc_do_setnewda(const struct i3c_device_desc *target, struct i3c_ccc_address new_da)
159 {
160 	struct i3c_driver_data *bus_data = (struct i3c_driver_data *)target->bus->data;
161 	struct i3c_ccc_payload ccc_payload;
162 	struct i3c_ccc_target_payload ccc_tgt_payload;
163 	uint8_t new_dyn_addr;
164 
165 	__ASSERT_NO_MSG(target != NULL);
166 	__ASSERT_NO_MSG(target->bus != NULL);
167 
168 	if (target->dynamic_addr == 0U) {
169 		return -EINVAL;
170 	}
171 
172 	/*
173 	 * Note that the 7-bit address needs to start at bit 1
174 	 * (aka left-justified). So shift left by 1;
175 	 */
176 	new_dyn_addr = new_da.addr << 1;
177 
178 	/* check that initial dynamic address is free before setting it */
179 	if (target->dynamic_addr != new_da.addr) {
180 		if (!i3c_addr_slots_is_free(&bus_data->attached_dev.addr_slots, new_da.addr)) {
181 			return -EINVAL;
182 		}
183 	}
184 
185 	ccc_tgt_payload.addr = target->dynamic_addr;
186 	ccc_tgt_payload.rnw = 0;
187 	ccc_tgt_payload.data = &new_dyn_addr;
188 	ccc_tgt_payload.data_len = 1;
189 
190 	memset(&ccc_payload, 0, sizeof(ccc_payload));
191 	ccc_payload.ccc.id = I3C_CCC_SETNEWDA;
192 	ccc_payload.targets.payloads = &ccc_tgt_payload;
193 	ccc_payload.targets.num_targets = 1;
194 
195 	return i3c_do_ccc(target->bus, &ccc_payload);
196 }
197 
i3c_ccc_do_events_all_set(const struct device * controller,bool enable,struct i3c_ccc_events * events)198 int i3c_ccc_do_events_all_set(const struct device *controller,
199 			      bool enable, struct i3c_ccc_events *events)
200 {
201 	struct i3c_ccc_payload ccc_payload;
202 
203 	__ASSERT_NO_MSG(controller != NULL);
204 
205 	memset(&ccc_payload, 0, sizeof(ccc_payload));
206 
207 	ccc_payload.ccc.id = enable ? I3C_CCC_ENEC(true) : I3C_CCC_DISEC(true);
208 
209 	ccc_payload.ccc.data = &events->events;
210 	ccc_payload.ccc.data_len = sizeof(events->events);
211 
212 	return i3c_do_ccc(controller, &ccc_payload);
213 }
214 
i3c_ccc_do_events_set(struct i3c_device_desc * target,bool enable,struct i3c_ccc_events * events)215 int i3c_ccc_do_events_set(struct i3c_device_desc *target,
216 			  bool enable, struct i3c_ccc_events *events)
217 {
218 	struct i3c_ccc_payload ccc_payload;
219 	struct i3c_ccc_target_payload ccc_tgt_payload;
220 
221 	__ASSERT_NO_MSG(target != NULL);
222 	__ASSERT_NO_MSG(target->bus != NULL);
223 
224 	if (target->dynamic_addr == 0U) {
225 		return -EINVAL;
226 	}
227 
228 	ccc_tgt_payload.addr = target->dynamic_addr;
229 	ccc_tgt_payload.rnw = 0;
230 	ccc_tgt_payload.data = &events->events;
231 	ccc_tgt_payload.data_len = sizeof(events->events);
232 
233 	memset(&ccc_payload, 0, sizeof(ccc_payload));
234 	ccc_payload.ccc.id = enable ? I3C_CCC_ENEC(false) : I3C_CCC_DISEC(false);
235 	ccc_payload.targets.payloads = &ccc_tgt_payload;
236 	ccc_payload.targets.num_targets = 1;
237 
238 	return i3c_do_ccc(target->bus, &ccc_payload);
239 }
240 
i3c_ccc_do_setmwl_all(const struct device * controller,const struct i3c_ccc_mwl * mwl)241 int i3c_ccc_do_setmwl_all(const struct device *controller,
242 			  const struct i3c_ccc_mwl *mwl)
243 {
244 	struct i3c_ccc_payload ccc_payload;
245 	uint8_t data[2];
246 
247 	__ASSERT_NO_MSG(controller != NULL);
248 
249 	memset(&ccc_payload, 0, sizeof(ccc_payload));
250 
251 	ccc_payload.ccc.id = I3C_CCC_SETMWL(true);
252 
253 	ccc_payload.ccc.data = &data[0];
254 	ccc_payload.ccc.data_len = sizeof(data);
255 
256 	/* The actual data is MSB first. So order the data. */
257 	data[0] = (uint8_t)((mwl->len & 0xFF00U) >> 8);
258 	data[1] = (uint8_t)(mwl->len & 0xFFU);
259 
260 	return i3c_do_ccc(controller, &ccc_payload);
261 }
262 
i3c_ccc_do_setmwl(const struct i3c_device_desc * target,const struct i3c_ccc_mwl * mwl)263 int i3c_ccc_do_setmwl(const struct i3c_device_desc *target,
264 		      const struct i3c_ccc_mwl *mwl)
265 {
266 	struct i3c_ccc_payload ccc_payload;
267 	struct i3c_ccc_target_payload ccc_tgt_payload;
268 	uint8_t data[2];
269 
270 	__ASSERT_NO_MSG(target != NULL);
271 	__ASSERT_NO_MSG(target->bus != NULL);
272 
273 	memset(&ccc_payload, 0, sizeof(ccc_payload));
274 
275 	ccc_tgt_payload.addr = target->dynamic_addr;
276 	ccc_tgt_payload.rnw = 0;
277 	ccc_tgt_payload.data = &data[0];
278 	ccc_tgt_payload.data_len = sizeof(data);
279 
280 	ccc_payload.ccc.id = I3C_CCC_SETMWL(false);
281 	ccc_payload.targets.payloads = &ccc_tgt_payload;
282 	ccc_payload.targets.num_targets = 1;
283 
284 	/* The actual length is MSB first. So order the data. */
285 	data[0] = (uint8_t)((mwl->len & 0xFF00U) >> 8);
286 	data[1] = (uint8_t)(mwl->len & 0xFFU);
287 
288 	return i3c_do_ccc(target->bus, &ccc_payload);
289 }
290 
i3c_ccc_do_getmwl(const struct i3c_device_desc * target,struct i3c_ccc_mwl * mwl)291 int i3c_ccc_do_getmwl(const struct i3c_device_desc *target,
292 		      struct i3c_ccc_mwl *mwl)
293 {
294 	struct i3c_ccc_payload ccc_payload;
295 	struct i3c_ccc_target_payload ccc_tgt_payload;
296 	uint8_t data[2];
297 	int ret;
298 
299 	__ASSERT_NO_MSG(target != NULL);
300 	__ASSERT_NO_MSG(target->bus != NULL);
301 	__ASSERT_NO_MSG(mwl != NULL);
302 
303 	ccc_tgt_payload.addr = target->dynamic_addr;
304 	ccc_tgt_payload.rnw = 1;
305 	ccc_tgt_payload.data = &data[0];
306 	ccc_tgt_payload.data_len = sizeof(data);
307 
308 	memset(&ccc_payload, 0, sizeof(ccc_payload));
309 	ccc_payload.ccc.id = I3C_CCC_GETMWL;
310 	ccc_payload.targets.payloads = &ccc_tgt_payload;
311 	ccc_payload.targets.num_targets = 1;
312 
313 	ret = i3c_do_ccc(target->bus, &ccc_payload);
314 
315 	if (ret == 0) {
316 		/* The actual length is MSB first. So order the data. */
317 		mwl->len = (data[0] << 8) | data[1];
318 	}
319 
320 	return ret;
321 }
322 
i3c_ccc_do_setmrl_all(const struct device * controller,const struct i3c_ccc_mrl * mrl,bool has_ibi_size)323 int i3c_ccc_do_setmrl_all(const struct device *controller,
324 			  const struct i3c_ccc_mrl *mrl,
325 			  bool has_ibi_size)
326 {
327 	struct i3c_ccc_payload ccc_payload;
328 	uint8_t data[3];
329 
330 	__ASSERT_NO_MSG(controller != NULL);
331 
332 	memset(&ccc_payload, 0, sizeof(ccc_payload));
333 
334 	ccc_payload.ccc.id = I3C_CCC_SETMRL(true);
335 
336 	ccc_payload.ccc.data = &data[0];
337 	ccc_payload.ccc.data_len = has_ibi_size ? 3 : 2;
338 
339 	/* The actual length is MSB first. So order the data. */
340 	data[0] = (uint8_t)((mrl->len & 0xFF00U) >> 8);
341 	data[1] = (uint8_t)(mrl->len & 0xFFU);
342 
343 	if (has_ibi_size) {
344 		data[2] = mrl->ibi_len;
345 	}
346 
347 	return i3c_do_ccc(controller, &ccc_payload);
348 }
349 
i3c_ccc_do_setmrl(const struct i3c_device_desc * target,const struct i3c_ccc_mrl * mrl)350 int i3c_ccc_do_setmrl(const struct i3c_device_desc *target,
351 		      const struct i3c_ccc_mrl *mrl)
352 {
353 	struct i3c_ccc_payload ccc_payload;
354 	struct i3c_ccc_target_payload ccc_tgt_payload;
355 	uint8_t data[3];
356 
357 	__ASSERT_NO_MSG(target != NULL);
358 	__ASSERT_NO_MSG(target->bus != NULL);
359 
360 	memset(&ccc_payload, 0, sizeof(ccc_payload));
361 
362 	ccc_tgt_payload.addr = target->dynamic_addr;
363 	ccc_tgt_payload.rnw = 0;
364 	ccc_tgt_payload.data = &data[0];
365 
366 	ccc_payload.ccc.id = I3C_CCC_SETMRL(false);
367 	ccc_payload.targets.payloads = &ccc_tgt_payload;
368 	ccc_payload.targets.num_targets = 1;
369 
370 	/* The actual length is MSB first. So order the data. */
371 	data[0] = (uint8_t)((mrl->len & 0xFF00U) >> 8);
372 	data[1] = (uint8_t)(mrl->len & 0xFFU);
373 
374 	if ((target->bcr & I3C_BCR_IBI_PAYLOAD_HAS_DATA_BYTE)
375 	    == I3C_BCR_IBI_PAYLOAD_HAS_DATA_BYTE) {
376 		ccc_tgt_payload.data_len = 3;
377 
378 		data[2] = mrl->ibi_len;
379 	} else {
380 		ccc_tgt_payload.data_len = 2;
381 	}
382 
383 	return i3c_do_ccc(target->bus, &ccc_payload);
384 }
385 
i3c_ccc_do_getmrl(const struct i3c_device_desc * target,struct i3c_ccc_mrl * mrl)386 int i3c_ccc_do_getmrl(const struct i3c_device_desc *target,
387 		      struct i3c_ccc_mrl *mrl)
388 {
389 	struct i3c_ccc_payload ccc_payload;
390 	struct i3c_ccc_target_payload ccc_tgt_payload;
391 	uint8_t data[3];
392 	bool has_ibi_sz;
393 	int ret;
394 
395 	__ASSERT_NO_MSG(target != NULL);
396 	__ASSERT_NO_MSG(target->bus != NULL);
397 	__ASSERT_NO_MSG(mrl != NULL);
398 
399 	has_ibi_sz = (target->bcr & I3C_BCR_IBI_PAYLOAD_HAS_DATA_BYTE)
400 		     == I3C_BCR_IBI_PAYLOAD_HAS_DATA_BYTE;
401 
402 	ccc_tgt_payload.addr = target->dynamic_addr;
403 	ccc_tgt_payload.rnw = 1;
404 	ccc_tgt_payload.data = &data[0];
405 	ccc_tgt_payload.data_len = has_ibi_sz ? 3 : 2;
406 
407 	memset(&ccc_payload, 0, sizeof(ccc_payload));
408 	ccc_payload.ccc.id = I3C_CCC_GETMRL;
409 	ccc_payload.targets.payloads = &ccc_tgt_payload;
410 	ccc_payload.targets.num_targets = 1;
411 
412 	ret = i3c_do_ccc(target->bus, &ccc_payload);
413 
414 	if (ret == 0) {
415 		/* The actual length is MSB first. So order the data. */
416 		mrl->len = (data[0] << 8) | data[1];
417 
418 		if (has_ibi_sz) {
419 			mrl->ibi_len = data[2];
420 		}
421 	}
422 
423 	return ret;
424 }
425 
i3c_ccc_do_getstatus(const struct i3c_device_desc * target,union i3c_ccc_getstatus * status,enum i3c_ccc_getstatus_fmt fmt,enum i3c_ccc_getstatus_defbyte defbyte)426 int i3c_ccc_do_getstatus(const struct i3c_device_desc *target,
427 			 union i3c_ccc_getstatus *status,
428 			 enum i3c_ccc_getstatus_fmt fmt,
429 			 enum i3c_ccc_getstatus_defbyte defbyte)
430 {
431 	struct i3c_ccc_payload ccc_payload;
432 	struct i3c_ccc_target_payload ccc_tgt_payload;
433 	uint8_t defining_byte;
434 	uint8_t data[2];
435 	int ret;
436 
437 	__ASSERT_NO_MSG(target != NULL);
438 	__ASSERT_NO_MSG(target->bus != NULL);
439 	__ASSERT_NO_MSG(status != NULL);
440 
441 	ccc_tgt_payload.addr = target->dynamic_addr;
442 	ccc_tgt_payload.rnw = 1;
443 	ccc_tgt_payload.data = &data[0];
444 
445 	if (fmt == GETSTATUS_FORMAT_1) {
446 		ccc_tgt_payload.data_len = 2;
447 	} else if (fmt == GETSTATUS_FORMAT_2) {
448 		switch (defbyte) {
449 		case GETSTATUS_FORMAT_2_TGTSTAT:
450 			__fallthrough;
451 		case GETSTATUS_FORMAT_2_PRECR:
452 			ccc_tgt_payload.data_len = 2;
453 			break;
454 		default:
455 			ret = -EINVAL;
456 			goto out;
457 		}
458 	} else {
459 		ret = -EINVAL;
460 		goto out;
461 	}
462 
463 	memset(&ccc_payload, 0, sizeof(ccc_payload));
464 	ccc_payload.ccc.id = I3C_CCC_GETSTATUS;
465 	ccc_payload.targets.payloads = &ccc_tgt_payload;
466 	ccc_payload.targets.num_targets = 1;
467 
468 	if (fmt == GETSTATUS_FORMAT_2) {
469 		defining_byte = (uint8_t)defbyte;
470 
471 		ccc_payload.ccc.data = &defining_byte;
472 		ccc_payload.ccc.data_len = 1;
473 	}
474 
475 	ret = i3c_do_ccc(target->bus, &ccc_payload);
476 
477 	if (ret == 0) {
478 		/* Received data is MSB first. So order the data. */
479 		if (fmt == GETSTATUS_FORMAT_1) {
480 			status->fmt1.status = (data[0] << 8) | data[1];
481 		} else if (fmt == GETSTATUS_FORMAT_2) {
482 			switch (defbyte) {
483 			case GETSTATUS_FORMAT_2_TGTSTAT:
484 				__fallthrough;
485 			case GETSTATUS_FORMAT_2_PRECR:
486 				status->fmt2.raw_u16 = (data[0] << 8) | data[1];
487 				break;
488 			default:
489 				break;
490 			}
491 		}
492 	}
493 
494 out:
495 	return ret;
496 }
497