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/byteorder.h>
11 #include <zephyr/sys/__assert.h>
12
13 #include <zephyr/drivers/i3c.h>
14
15 #include <zephyr/logging/log.h>
16 LOG_MODULE_DECLARE(i3c, CONFIG_I3C_LOG_LEVEL);
17
i3c_ccc_do_getbcr(struct i3c_device_desc * target,struct i3c_ccc_getbcr * bcr)18 int i3c_ccc_do_getbcr(struct i3c_device_desc *target,
19 struct i3c_ccc_getbcr *bcr)
20 {
21 struct i3c_ccc_payload ccc_payload;
22 struct i3c_ccc_target_payload ccc_tgt_payload;
23
24 __ASSERT_NO_MSG(target != NULL);
25 __ASSERT_NO_MSG(target->bus != NULL);
26 __ASSERT_NO_MSG(bcr != NULL);
27
28 ccc_tgt_payload.addr = target->dynamic_addr;
29 ccc_tgt_payload.rnw = 1;
30 ccc_tgt_payload.data = &bcr->bcr;
31 ccc_tgt_payload.data_len = sizeof(bcr->bcr);
32
33 memset(&ccc_payload, 0, sizeof(ccc_payload));
34 ccc_payload.ccc.id = I3C_CCC_GETBCR;
35 ccc_payload.targets.payloads = &ccc_tgt_payload;
36 ccc_payload.targets.num_targets = 1;
37
38 return i3c_do_ccc(target->bus, &ccc_payload);
39 }
40
i3c_ccc_do_getdcr(struct i3c_device_desc * target,struct i3c_ccc_getdcr * dcr)41 int i3c_ccc_do_getdcr(struct i3c_device_desc *target,
42 struct i3c_ccc_getdcr *dcr)
43 {
44 struct i3c_ccc_payload ccc_payload;
45 struct i3c_ccc_target_payload ccc_tgt_payload;
46
47 __ASSERT_NO_MSG(target != NULL);
48 __ASSERT_NO_MSG(target->bus != NULL);
49 __ASSERT_NO_MSG(dcr != NULL);
50
51 ccc_tgt_payload.addr = target->dynamic_addr;
52 ccc_tgt_payload.rnw = 1;
53 ccc_tgt_payload.data = &dcr->dcr;
54 ccc_tgt_payload.data_len = sizeof(dcr->dcr);
55
56 memset(&ccc_payload, 0, sizeof(ccc_payload));
57 ccc_payload.ccc.id = I3C_CCC_GETDCR;
58 ccc_payload.targets.payloads = &ccc_tgt_payload;
59 ccc_payload.targets.num_targets = 1;
60
61 return i3c_do_ccc(target->bus, &ccc_payload);
62 }
63
i3c_ccc_do_getpid(struct i3c_device_desc * target,struct i3c_ccc_getpid * pid)64 int i3c_ccc_do_getpid(struct i3c_device_desc *target,
65 struct i3c_ccc_getpid *pid)
66 {
67 struct i3c_ccc_payload ccc_payload;
68 struct i3c_ccc_target_payload ccc_tgt_payload;
69
70 __ASSERT_NO_MSG(target != NULL);
71 __ASSERT_NO_MSG(target->bus != NULL);
72 __ASSERT_NO_MSG(pid != NULL);
73
74 ccc_tgt_payload.addr = target->dynamic_addr;
75 ccc_tgt_payload.rnw = 1;
76 ccc_tgt_payload.data = &pid->pid[0];
77 ccc_tgt_payload.data_len = sizeof(pid->pid);
78
79 memset(&ccc_payload, 0, sizeof(ccc_payload));
80 ccc_payload.ccc.id = I3C_CCC_GETPID;
81 ccc_payload.targets.payloads = &ccc_tgt_payload;
82 ccc_payload.targets.num_targets = 1;
83
84 return i3c_do_ccc(target->bus, &ccc_payload);
85 }
86
i3c_ccc_do_rstact_all(const struct device * controller,enum i3c_ccc_rstact_defining_byte action)87 int i3c_ccc_do_rstact_all(const struct device *controller,
88 enum i3c_ccc_rstact_defining_byte action)
89 {
90 struct i3c_ccc_payload ccc_payload;
91 uint8_t def_byte;
92
93 __ASSERT_NO_MSG(controller != NULL);
94
95 memset(&ccc_payload, 0, sizeof(ccc_payload));
96 ccc_payload.ccc.id = I3C_CCC_RSTACT(true);
97
98 def_byte = (uint8_t)action;
99 ccc_payload.ccc.data = &def_byte;
100 ccc_payload.ccc.data_len = 1U;
101
102 return i3c_do_ccc(controller, &ccc_payload);
103 }
104
i3c_ccc_do_rstact(const struct i3c_device_desc * target,enum i3c_ccc_rstact_defining_byte action,bool get,uint8_t * data)105 int i3c_ccc_do_rstact(const struct i3c_device_desc *target,
106 enum i3c_ccc_rstact_defining_byte action,
107 bool get,
108 uint8_t *data)
109 {
110 struct i3c_ccc_payload ccc_payload;
111 struct i3c_ccc_target_payload ccc_tgt_payload;
112 uint8_t def_byte;
113
114 __ASSERT_NO_MSG(target != NULL);
115 __ASSERT_NO_MSG(target->bus != NULL);
116
117 memset(&ccc_payload, 0, sizeof(ccc_payload));
118
119 ccc_tgt_payload.addr = target->dynamic_addr;
120 if (get) {
121 __ASSERT_NO_MSG(data != NULL);
122
123 ccc_tgt_payload.rnw = 1;
124 ccc_tgt_payload.data = data;
125 ccc_tgt_payload.data_len = sizeof(*data);
126 } else {
127 ccc_tgt_payload.rnw = 0;
128 }
129
130 ccc_payload.ccc.id = I3C_CCC_RSTACT(false);
131 def_byte = (uint8_t)action;
132 ccc_payload.ccc.data = &def_byte;
133 ccc_payload.ccc.data_len = 1U;
134 ccc_payload.targets.payloads = &ccc_tgt_payload;
135 ccc_payload.targets.num_targets = 1;
136
137 return i3c_do_ccc(target->bus, &ccc_payload);
138 }
139
i3c_ccc_do_rstdaa_all(const struct device * controller)140 int i3c_ccc_do_rstdaa_all(const struct device *controller)
141 {
142 struct i3c_ccc_payload ccc_payload;
143
144 __ASSERT_NO_MSG(controller != NULL);
145
146 memset(&ccc_payload, 0, sizeof(ccc_payload));
147 ccc_payload.ccc.id = I3C_CCC_RSTDAA;
148
149 return i3c_do_ccc(controller, &ccc_payload);
150 }
151
i3c_ccc_do_setdasa(const struct i3c_device_desc * target,struct i3c_ccc_address da)152 int i3c_ccc_do_setdasa(const struct i3c_device_desc *target, struct i3c_ccc_address da)
153 {
154 struct i3c_ccc_payload ccc_payload;
155 struct i3c_ccc_target_payload ccc_tgt_payload;
156
157 __ASSERT_NO_MSG(target != NULL);
158 __ASSERT_NO_MSG(target->bus != NULL);
159
160 if ((target->static_addr == 0U) || (target->dynamic_addr != 0U)) {
161 return -EINVAL;
162 }
163
164 ccc_tgt_payload.addr = target->static_addr;
165 ccc_tgt_payload.rnw = 0;
166 ccc_tgt_payload.data = (uint8_t *)&da.addr;
167 ccc_tgt_payload.data_len = 1;
168
169 memset(&ccc_payload, 0, sizeof(ccc_payload));
170 ccc_payload.ccc.id = I3C_CCC_SETDASA;
171 ccc_payload.targets.payloads = &ccc_tgt_payload;
172 ccc_payload.targets.num_targets = 1;
173
174 return i3c_do_ccc(target->bus, &ccc_payload);
175 }
176
i3c_ccc_do_setnewda(const struct i3c_device_desc * target,struct i3c_ccc_address new_da)177 int i3c_ccc_do_setnewda(const struct i3c_device_desc *target, struct i3c_ccc_address new_da)
178 {
179 struct i3c_ccc_payload ccc_payload;
180 struct i3c_ccc_target_payload ccc_tgt_payload;
181
182 __ASSERT_NO_MSG(target != NULL);
183 __ASSERT_NO_MSG(target->bus != NULL);
184
185 if (target->dynamic_addr == 0U) {
186 return -EINVAL;
187 }
188
189 ccc_tgt_payload.addr = target->dynamic_addr;
190 ccc_tgt_payload.rnw = 0;
191 ccc_tgt_payload.data = (uint8_t *)&new_da.addr;
192 ccc_tgt_payload.data_len = 1;
193
194 memset(&ccc_payload, 0, sizeof(ccc_payload));
195 ccc_payload.ccc.id = I3C_CCC_SETNEWDA;
196 ccc_payload.targets.payloads = &ccc_tgt_payload;
197 ccc_payload.targets.num_targets = 1;
198
199 return i3c_do_ccc(target->bus, &ccc_payload);
200 }
201
i3c_ccc_do_events_all_set(const struct device * controller,bool enable,struct i3c_ccc_events * events)202 int i3c_ccc_do_events_all_set(const struct device *controller,
203 bool enable, struct i3c_ccc_events *events)
204 {
205 struct i3c_ccc_payload ccc_payload;
206
207 __ASSERT_NO_MSG(controller != NULL);
208
209 memset(&ccc_payload, 0, sizeof(ccc_payload));
210
211 ccc_payload.ccc.id = enable ? I3C_CCC_ENEC(true) : I3C_CCC_DISEC(true);
212
213 ccc_payload.ccc.data = &events->events;
214 ccc_payload.ccc.data_len = sizeof(events->events);
215
216 return i3c_do_ccc(controller, &ccc_payload);
217 }
218
i3c_ccc_do_events_set(struct i3c_device_desc * target,bool enable,struct i3c_ccc_events * events)219 int i3c_ccc_do_events_set(struct i3c_device_desc *target,
220 bool enable, struct i3c_ccc_events *events)
221 {
222 struct i3c_ccc_payload ccc_payload;
223 struct i3c_ccc_target_payload ccc_tgt_payload;
224
225 __ASSERT_NO_MSG(target != NULL);
226 __ASSERT_NO_MSG(target->bus != NULL);
227
228 if (target->dynamic_addr == 0U) {
229 return -EINVAL;
230 }
231
232 ccc_tgt_payload.addr = target->dynamic_addr;
233 ccc_tgt_payload.rnw = 0;
234 ccc_tgt_payload.data = &events->events;
235 ccc_tgt_payload.data_len = sizeof(events->events);
236
237 memset(&ccc_payload, 0, sizeof(ccc_payload));
238 ccc_payload.ccc.id = enable ? I3C_CCC_ENEC(false) : I3C_CCC_DISEC(false);
239 ccc_payload.targets.payloads = &ccc_tgt_payload;
240 ccc_payload.targets.num_targets = 1;
241
242 return i3c_do_ccc(target->bus, &ccc_payload);
243 }
244
i3c_ccc_do_entas(const struct i3c_device_desc * target,uint8_t as)245 int i3c_ccc_do_entas(const struct i3c_device_desc *target, uint8_t as)
246 {
247 struct i3c_ccc_payload ccc_payload;
248 struct i3c_ccc_target_payload ccc_tgt_payload;
249
250 __ASSERT_NO_MSG(target != NULL);
251 __ASSERT_NO_MSG(target->bus != NULL);
252 __ASSERT_NO_MSG(as <= 3);
253
254 memset(&ccc_payload, 0, sizeof(ccc_payload));
255
256 ccc_tgt_payload.addr = target->dynamic_addr;
257 ccc_tgt_payload.rnw = 0;
258
259 ccc_payload.ccc.id = I3C_CCC_ENTAS(as, false);
260 ccc_payload.targets.payloads = &ccc_tgt_payload;
261 ccc_payload.targets.num_targets = 1;
262
263 return i3c_do_ccc(target->bus, &ccc_payload);
264 }
265
i3c_ccc_do_entas_all(const struct device * controller,uint8_t as)266 int i3c_ccc_do_entas_all(const struct device *controller, uint8_t as)
267 {
268 struct i3c_ccc_payload ccc_payload;
269
270 __ASSERT_NO_MSG(controller != NULL);
271 __ASSERT_NO_MSG(as <= 3);
272
273 memset(&ccc_payload, 0, sizeof(ccc_payload));
274 ccc_payload.ccc.id = I3C_CCC_ENTAS(as, true);
275
276 return i3c_do_ccc(controller, &ccc_payload);
277 }
278
i3c_ccc_do_setmwl_all(const struct device * controller,const struct i3c_ccc_mwl * mwl)279 int i3c_ccc_do_setmwl_all(const struct device *controller,
280 const struct i3c_ccc_mwl *mwl)
281 {
282 struct i3c_ccc_payload ccc_payload;
283 uint8_t data[2];
284
285 __ASSERT_NO_MSG(controller != NULL);
286
287 memset(&ccc_payload, 0, sizeof(ccc_payload));
288
289 ccc_payload.ccc.id = I3C_CCC_SETMWL(true);
290
291 ccc_payload.ccc.data = &data[0];
292 ccc_payload.ccc.data_len = sizeof(data);
293
294 /* The actual data is MSB first. So order the data. */
295 sys_put_be16(mwl->len, data);
296
297 return i3c_do_ccc(controller, &ccc_payload);
298 }
299
i3c_ccc_do_setmwl(const struct i3c_device_desc * target,const struct i3c_ccc_mwl * mwl)300 int i3c_ccc_do_setmwl(const struct i3c_device_desc *target,
301 const struct i3c_ccc_mwl *mwl)
302 {
303 struct i3c_ccc_payload ccc_payload;
304 struct i3c_ccc_target_payload ccc_tgt_payload;
305 uint8_t data[2];
306
307 __ASSERT_NO_MSG(target != NULL);
308 __ASSERT_NO_MSG(target->bus != NULL);
309
310 memset(&ccc_payload, 0, sizeof(ccc_payload));
311
312 ccc_tgt_payload.addr = target->dynamic_addr;
313 ccc_tgt_payload.rnw = 0;
314 ccc_tgt_payload.data = &data[0];
315 ccc_tgt_payload.data_len = sizeof(data);
316
317 ccc_payload.ccc.id = I3C_CCC_SETMWL(false);
318 ccc_payload.targets.payloads = &ccc_tgt_payload;
319 ccc_payload.targets.num_targets = 1;
320
321 /* The actual length is MSB first. So order the data. */
322 sys_put_be16(mwl->len, data);
323
324 return i3c_do_ccc(target->bus, &ccc_payload);
325 }
326
i3c_ccc_do_getmwl(const struct i3c_device_desc * target,struct i3c_ccc_mwl * mwl)327 int i3c_ccc_do_getmwl(const struct i3c_device_desc *target,
328 struct i3c_ccc_mwl *mwl)
329 {
330 struct i3c_ccc_payload ccc_payload;
331 struct i3c_ccc_target_payload ccc_tgt_payload;
332 uint8_t data[2];
333 int ret;
334
335 __ASSERT_NO_MSG(target != NULL);
336 __ASSERT_NO_MSG(target->bus != NULL);
337 __ASSERT_NO_MSG(mwl != NULL);
338
339 ccc_tgt_payload.addr = target->dynamic_addr;
340 ccc_tgt_payload.rnw = 1;
341 ccc_tgt_payload.data = &data[0];
342 ccc_tgt_payload.data_len = sizeof(data);
343
344 memset(&ccc_payload, 0, sizeof(ccc_payload));
345 ccc_payload.ccc.id = I3C_CCC_GETMWL;
346 ccc_payload.targets.payloads = &ccc_tgt_payload;
347 ccc_payload.targets.num_targets = 1;
348
349 ret = i3c_do_ccc(target->bus, &ccc_payload);
350
351 if (ret == 0) {
352 /* The actual length is MSB first. So order the data. */
353 mwl->len = sys_get_be16(data);
354 }
355
356 return ret;
357 }
358
i3c_ccc_do_setmrl_all(const struct device * controller,const struct i3c_ccc_mrl * mrl,bool has_ibi_size)359 int i3c_ccc_do_setmrl_all(const struct device *controller,
360 const struct i3c_ccc_mrl *mrl,
361 bool has_ibi_size)
362 {
363 struct i3c_ccc_payload ccc_payload;
364 uint8_t data[3];
365
366 __ASSERT_NO_MSG(controller != NULL);
367
368 memset(&ccc_payload, 0, sizeof(ccc_payload));
369
370 ccc_payload.ccc.id = I3C_CCC_SETMRL(true);
371
372 ccc_payload.ccc.data = &data[0];
373 ccc_payload.ccc.data_len = has_ibi_size ? 3 : 2;
374
375 /* The actual length is MSB first. So order the data. */
376 sys_put_be16(mrl->len, data);
377
378 if (has_ibi_size) {
379 data[2] = mrl->ibi_len;
380 }
381
382 return i3c_do_ccc(controller, &ccc_payload);
383 }
384
i3c_ccc_do_setmrl(const struct i3c_device_desc * target,const struct i3c_ccc_mrl * mrl)385 int i3c_ccc_do_setmrl(const struct i3c_device_desc *target,
386 const struct i3c_ccc_mrl *mrl)
387 {
388 struct i3c_ccc_payload ccc_payload;
389 struct i3c_ccc_target_payload ccc_tgt_payload;
390 uint8_t data[3];
391
392 __ASSERT_NO_MSG(target != NULL);
393 __ASSERT_NO_MSG(target->bus != NULL);
394
395 memset(&ccc_payload, 0, sizeof(ccc_payload));
396
397 ccc_tgt_payload.addr = target->dynamic_addr;
398 ccc_tgt_payload.rnw = 0;
399 ccc_tgt_payload.data = &data[0];
400
401 ccc_payload.ccc.id = I3C_CCC_SETMRL(false);
402 ccc_payload.targets.payloads = &ccc_tgt_payload;
403 ccc_payload.targets.num_targets = 1;
404
405 /* The actual length is MSB first. So order the data. */
406 sys_put_be16(mrl->len, data);
407
408 if ((target->bcr & I3C_BCR_IBI_PAYLOAD_HAS_DATA_BYTE)
409 == I3C_BCR_IBI_PAYLOAD_HAS_DATA_BYTE) {
410 ccc_tgt_payload.data_len = 3;
411
412 data[2] = mrl->ibi_len;
413 } else {
414 ccc_tgt_payload.data_len = 2;
415 }
416
417 return i3c_do_ccc(target->bus, &ccc_payload);
418 }
419
i3c_ccc_do_getmrl(const struct i3c_device_desc * target,struct i3c_ccc_mrl * mrl)420 int i3c_ccc_do_getmrl(const struct i3c_device_desc *target,
421 struct i3c_ccc_mrl *mrl)
422 {
423 struct i3c_ccc_payload ccc_payload;
424 struct i3c_ccc_target_payload ccc_tgt_payload;
425 uint8_t data[3];
426 bool has_ibi_sz;
427 int ret;
428
429 __ASSERT_NO_MSG(target != NULL);
430 __ASSERT_NO_MSG(target->bus != NULL);
431 __ASSERT_NO_MSG(mrl != NULL);
432
433 has_ibi_sz = (target->bcr & I3C_BCR_IBI_PAYLOAD_HAS_DATA_BYTE)
434 == I3C_BCR_IBI_PAYLOAD_HAS_DATA_BYTE;
435
436 ccc_tgt_payload.addr = target->dynamic_addr;
437 ccc_tgt_payload.rnw = 1;
438 ccc_tgt_payload.data = &data[0];
439 ccc_tgt_payload.data_len = has_ibi_sz ? 3 : 2;
440
441 memset(&ccc_payload, 0, sizeof(ccc_payload));
442 ccc_payload.ccc.id = I3C_CCC_GETMRL;
443 ccc_payload.targets.payloads = &ccc_tgt_payload;
444 ccc_payload.targets.num_targets = 1;
445
446 ret = i3c_do_ccc(target->bus, &ccc_payload);
447
448 if (ret == 0) {
449 /* The actual length is MSB first. So order the data. */
450 mrl->len = sys_get_be16(data);
451
452 if (has_ibi_sz) {
453 mrl->ibi_len = data[2];
454 }
455 }
456
457 return ret;
458 }
459
i3c_ccc_do_enttm(const struct device * controller,enum i3c_ccc_enttm_defbyte defbyte)460 int i3c_ccc_do_enttm(const struct device *controller,
461 enum i3c_ccc_enttm_defbyte defbyte)
462 {
463 struct i3c_ccc_payload ccc_payload;
464 uint8_t def_byte;
465
466 __ASSERT_NO_MSG(controller != NULL);
467
468 memset(&ccc_payload, 0, sizeof(ccc_payload));
469 ccc_payload.ccc.id = I3C_CCC_ENTTM;
470
471 def_byte = (uint8_t)defbyte;
472 ccc_payload.ccc.data = &def_byte;
473 ccc_payload.ccc.data_len = 1U;
474
475 return i3c_do_ccc(controller, &ccc_payload);
476 }
477
i3c_ccc_do_deftgts_all(const struct device * controller,struct i3c_ccc_deftgts * deftgts)478 int i3c_ccc_do_deftgts_all(const struct device *controller,
479 struct i3c_ccc_deftgts *deftgts)
480 {
481 struct i3c_ccc_payload ccc_payload;
482
483 __ASSERT_NO_MSG(controller != NULL);
484 __ASSERT_NO_MSG(deftgts != NULL);
485
486 memset(&ccc_payload, 0, sizeof(ccc_payload));
487 ccc_payload.ccc.id = I3C_CCC_DEFTGTS;
488
489 ccc_payload.ccc.data = (uint8_t *)deftgts;
490 ccc_payload.ccc.data_len = sizeof(uint8_t) +
491 sizeof(struct i3c_ccc_deftgts_active_controller) +
492 (deftgts->count * sizeof(struct i3c_ccc_deftgts_target));
493
494 return i3c_do_ccc(controller, &ccc_payload);
495 }
496
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)497 int i3c_ccc_do_getstatus(const struct i3c_device_desc *target,
498 union i3c_ccc_getstatus *status,
499 enum i3c_ccc_getstatus_fmt fmt,
500 enum i3c_ccc_getstatus_defbyte defbyte)
501 {
502 struct i3c_ccc_payload ccc_payload;
503 struct i3c_ccc_target_payload ccc_tgt_payload;
504 uint8_t defining_byte;
505 uint8_t data[2];
506 int ret;
507
508 __ASSERT_NO_MSG(target != NULL);
509 __ASSERT_NO_MSG(target->bus != NULL);
510 __ASSERT_NO_MSG(status != NULL);
511
512 ccc_tgt_payload.addr = target->dynamic_addr;
513 ccc_tgt_payload.rnw = 1;
514 ccc_tgt_payload.data = &data[0];
515
516 if (fmt == GETSTATUS_FORMAT_1) {
517 ccc_tgt_payload.data_len = 2;
518 } else if (fmt == GETSTATUS_FORMAT_2) {
519 switch (defbyte) {
520 case GETSTATUS_FORMAT_2_TGTSTAT:
521 __fallthrough;
522 case GETSTATUS_FORMAT_2_PRECR:
523 ccc_tgt_payload.data_len = 2;
524 break;
525 default:
526 ret = -EINVAL;
527 goto out;
528 }
529 } else {
530 ret = -EINVAL;
531 goto out;
532 }
533
534 memset(&ccc_payload, 0, sizeof(ccc_payload));
535 ccc_payload.ccc.id = I3C_CCC_GETSTATUS;
536 ccc_payload.targets.payloads = &ccc_tgt_payload;
537 ccc_payload.targets.num_targets = 1;
538
539 if (fmt == GETSTATUS_FORMAT_2) {
540 defining_byte = (uint8_t)defbyte;
541
542 ccc_payload.ccc.data = &defining_byte;
543 ccc_payload.ccc.data_len = 1;
544 }
545
546 ret = i3c_do_ccc(target->bus, &ccc_payload);
547
548 if (ret == 0) {
549 /* Received data is MSB first. So order the data. */
550 if (fmt == GETSTATUS_FORMAT_1) {
551 status->fmt1.status = sys_get_be16(data);
552 } else if (fmt == GETSTATUS_FORMAT_2) {
553 switch (defbyte) {
554 case GETSTATUS_FORMAT_2_TGTSTAT:
555 __fallthrough;
556 case GETSTATUS_FORMAT_2_PRECR:
557 status->fmt2.raw_u16 = sys_get_be16(data);
558 break;
559 default:
560 break;
561 }
562 }
563 }
564
565 out:
566 return ret;
567 }
568
i3c_ccc_do_getcaps(const struct i3c_device_desc * target,union i3c_ccc_getcaps * caps,enum i3c_ccc_getcaps_fmt fmt,enum i3c_ccc_getcaps_defbyte defbyte)569 int i3c_ccc_do_getcaps(const struct i3c_device_desc *target,
570 union i3c_ccc_getcaps *caps,
571 enum i3c_ccc_getcaps_fmt fmt,
572 enum i3c_ccc_getcaps_defbyte defbyte)
573 {
574 struct i3c_ccc_payload ccc_payload;
575 struct i3c_ccc_target_payload ccc_tgt_payload;
576 uint8_t defining_byte;
577 uint8_t data[4];
578 uint8_t len;
579 int ret;
580
581 __ASSERT_NO_MSG(target != NULL);
582 __ASSERT_NO_MSG(target->bus != NULL);
583 __ASSERT_NO_MSG(caps != NULL);
584
585 ccc_tgt_payload.addr = target->dynamic_addr;
586 ccc_tgt_payload.rnw = 1;
587 ccc_tgt_payload.data = &data[0];
588
589 if (fmt == GETCAPS_FORMAT_1) {
590 /* Could be 1-4 Data Bytes Returned */
591 ccc_tgt_payload.data_len = 4;
592 } else if (fmt == GETCAPS_FORMAT_2) {
593 switch (defbyte) {
594 case GETCAPS_FORMAT_2_CRCAPS:
595 __fallthrough;
596 case GETCAPS_FORMAT_2_VTCAPS:
597 /* Could be 1-2 Data Bytes Returned*/
598 ccc_tgt_payload.data_len = 2;
599 break;
600 case GETCAPS_FORMAT_2_TGTCAPS:
601 __fallthrough;
602 case GETCAPS_FORMAT_2_TESTPAT:
603 /* Could be 1-4 Data Bytes Returned */
604 ccc_tgt_payload.data_len = 4;
605 break;
606 default:
607 ret = -EINVAL;
608 goto out;
609 }
610 } else {
611 ret = -EINVAL;
612 goto out;
613 }
614
615 memset(&ccc_payload, 0, sizeof(ccc_payload));
616 ccc_payload.ccc.id = I3C_CCC_GETCAPS;
617 ccc_payload.targets.payloads = &ccc_tgt_payload;
618 ccc_payload.targets.num_targets = 1;
619
620 if (fmt == GETCAPS_FORMAT_2) {
621 defining_byte = (uint8_t)defbyte;
622
623 ccc_payload.ccc.data = &defining_byte;
624 ccc_payload.ccc.data_len = 1;
625 }
626
627 ret = i3c_do_ccc(target->bus, &ccc_payload);
628
629 if (ret == 0) {
630 /* GETCAPS will return a variable length */
631 len = ccc_tgt_payload.num_xfer;
632
633 if (fmt == GETCAPS_FORMAT_1) {
634 memcpy(caps->fmt1.getcaps, data, len);
635 /* for values not received, assume default (1'b0) */
636 memset(&caps->fmt1.getcaps[len], 0, sizeof(caps->fmt1.getcaps) - len);
637 } else if (fmt == GETCAPS_FORMAT_2) {
638 switch (defbyte) {
639 case GETCAPS_FORMAT_2_CRCAPS:
640 memcpy(caps->fmt2.crcaps, data, len);
641 /* for values not received, assume default (1'b0) */
642 memset(&caps->fmt2.crcaps[len], 0, sizeof(caps->fmt2.crcaps) - len);
643 break;
644 case GETCAPS_FORMAT_2_VTCAPS:
645 memcpy(caps->fmt2.vtcaps, data, len);
646 /* for values not received, assume default (1'b0) */
647 memset(&caps->fmt2.vtcaps[len], 0, sizeof(caps->fmt2.vtcaps) - len);
648 break;
649 case GETCAPS_FORMAT_2_TGTCAPS:
650 memcpy(caps->fmt2.tgtcaps, data, len);
651 /* for values not received, assume default (1'b0) */
652 memset(&caps->fmt2.tgtcaps[len], 0,
653 sizeof(caps->fmt2.tgtcaps) - len);
654 break;
655 case GETCAPS_FORMAT_2_TESTPAT:
656 /* should always be 4 data bytes */
657 caps->fmt2.testpat = sys_get_be32(data);
658 break;
659 default:
660 break;
661 }
662 }
663 }
664
665 out:
666 return ret;
667 }
668
i3c_ccc_do_setvendor(const struct i3c_device_desc * target,uint8_t id,uint8_t * payload,size_t len)669 int i3c_ccc_do_setvendor(const struct i3c_device_desc *target,
670 uint8_t id,
671 uint8_t *payload,
672 size_t len)
673 {
674 struct i3c_ccc_payload ccc_payload;
675
676 __ASSERT_NO_MSG(target != NULL);
677
678 /* CCC must be between 0xE0 and 0xFE, the total range of this is 0x1E */
679 if (id > 0x1E) {
680 return -EINVAL;
681 }
682
683 memset(&ccc_payload, 0, sizeof(ccc_payload));
684 ccc_payload.ccc.id = I3C_CCC_VENDOR(false, id);
685 ccc_payload.ccc.data = payload;
686 ccc_payload.ccc.data_len = len;
687
688 return i3c_do_ccc(target->bus, &ccc_payload);
689 }
690
i3c_ccc_do_getvendor(const struct i3c_device_desc * target,uint8_t id,uint8_t * payload,size_t len,size_t * num_xfer)691 int i3c_ccc_do_getvendor(const struct i3c_device_desc *target,
692 uint8_t id,
693 uint8_t *payload,
694 size_t len,
695 size_t *num_xfer)
696 {
697 struct i3c_ccc_payload ccc_payload;
698 struct i3c_ccc_target_payload ccc_tgt_payload;
699 int ret;
700
701 __ASSERT_NO_MSG(target != NULL);
702
703 /* CCC must be between 0xE0 and 0xFE, the total range of this is 0x1E */
704 if (id > 0x1E) {
705 return -EINVAL;
706 }
707
708 ccc_tgt_payload.addr = target->dynamic_addr;
709 ccc_tgt_payload.rnw = 1;
710 ccc_tgt_payload.data = payload;
711 ccc_tgt_payload.data_len = len;
712
713 memset(&ccc_payload, 0, sizeof(ccc_payload));
714 ccc_payload.ccc.id = I3C_CCC_VENDOR(false, id);
715 ccc_payload.targets.payloads = &ccc_tgt_payload;
716 ccc_payload.targets.num_targets = 1;
717
718 ret = i3c_do_ccc(target->bus, &ccc_payload);
719
720 if (ret == 0) {
721 *num_xfer = ccc_tgt_payload.num_xfer;
722 }
723
724 return ret;
725 }
726
i3c_ccc_do_getvendor_defbyte(const struct i3c_device_desc * target,uint8_t id,uint8_t defbyte,uint8_t * payload,size_t len,size_t * num_xfer)727 int i3c_ccc_do_getvendor_defbyte(const struct i3c_device_desc *target,
728 uint8_t id,
729 uint8_t defbyte,
730 uint8_t *payload,
731 size_t len,
732 size_t *num_xfer)
733 {
734 struct i3c_ccc_payload ccc_payload;
735 struct i3c_ccc_target_payload ccc_tgt_payload;
736 int ret;
737
738 __ASSERT_NO_MSG(target != NULL);
739
740 /* CCC must be between 0xE0 and 0xFE, the total range of this is 0x1E */
741 if (id > 0x1E) {
742 return -EINVAL;
743 }
744
745 ccc_tgt_payload.addr = target->dynamic_addr;
746 ccc_tgt_payload.rnw = 1;
747 ccc_tgt_payload.data = payload;
748 ccc_tgt_payload.data_len = len;
749
750 memset(&ccc_payload, 0, sizeof(ccc_payload));
751 ccc_payload.ccc.id = I3C_CCC_VENDOR(false, id);
752 ccc_payload.ccc.data = &defbyte;
753 ccc_payload.ccc.data_len = 1;
754 ccc_payload.targets.payloads = &ccc_tgt_payload;
755 ccc_payload.targets.num_targets = 1;
756
757 ret = i3c_do_ccc(target->bus, &ccc_payload);
758
759 if (ret == 0) {
760 *num_xfer = ccc_tgt_payload.num_xfer;
761 }
762
763 return ret;
764 }
765
i3c_ccc_do_setvendor_all(const struct device * controller,uint8_t id,uint8_t * payload,size_t len)766 int i3c_ccc_do_setvendor_all(const struct device *controller,
767 uint8_t id,
768 uint8_t *payload,
769 size_t len)
770 {
771 struct i3c_ccc_payload ccc_payload;
772
773 __ASSERT_NO_MSG(controller != NULL);
774
775 /* CCC must be between 0x61 and 0x7F, the total range of this is 0x1E */
776 if (id > 0x1E) {
777 return -EINVAL;
778 }
779
780 memset(&ccc_payload, 0, sizeof(ccc_payload));
781 ccc_payload.ccc.id = I3C_CCC_VENDOR(true, id);
782 ccc_payload.ccc.data = payload;
783 ccc_payload.ccc.data_len = len;
784
785 return i3c_do_ccc(controller, &ccc_payload);
786 }
787
i3c_ccc_do_setaasa_all(const struct device * controller)788 int i3c_ccc_do_setaasa_all(const struct device *controller)
789 {
790 struct i3c_ccc_payload ccc_payload;
791
792 __ASSERT_NO_MSG(controller != NULL);
793
794 memset(&ccc_payload, 0, sizeof(ccc_payload));
795 ccc_payload.ccc.id = I3C_CCC_SETAASA;
796
797 return i3c_do_ccc(controller, &ccc_payload);
798 }
799
i3c_ccc_do_getmxds(const struct i3c_device_desc * target,union i3c_ccc_getmxds * mxds,enum i3c_ccc_getmxds_fmt fmt,enum i3c_ccc_getmxds_defbyte defbyte)800 int i3c_ccc_do_getmxds(const struct i3c_device_desc *target,
801 union i3c_ccc_getmxds *mxds,
802 enum i3c_ccc_getmxds_fmt fmt,
803 enum i3c_ccc_getmxds_defbyte defbyte)
804 {
805 struct i3c_ccc_payload ccc_payload;
806 struct i3c_ccc_target_payload ccc_tgt_payload;
807 uint8_t defining_byte;
808 uint8_t data[5];
809 uint8_t len;
810 int ret;
811
812 __ASSERT_NO_MSG(target != NULL);
813 __ASSERT_NO_MSG(target->bus != NULL);
814 __ASSERT_NO_MSG(mxds != NULL);
815
816 ccc_tgt_payload.addr = target->dynamic_addr;
817 ccc_tgt_payload.rnw = 1;
818 ccc_tgt_payload.data = &data[0];
819
820 if ((fmt == GETMXDS_FORMAT_1) || (fmt == GETMXDS_FORMAT_2)) {
821 /* Could be 2 or 5 Data Bytes Returned */
822 ccc_tgt_payload.data_len = sizeof(((union i3c_ccc_getmxds *)0)->fmt2);
823 } else if (fmt == GETMXDS_FORMAT_3) {
824 switch (defbyte) {
825 case GETMXDS_FORMAT_3_WRRDTURN:
826 /* Could be 2 or 5 Data Bytes Returned */
827 ccc_tgt_payload.data_len =
828 sizeof(((union i3c_ccc_getmxds *)0)->fmt3.wrrdturn);
829 break;
830 case GETMXDS_FORMAT_3_CRHDLY:
831 /* Only 1 Byte returned */
832 ccc_tgt_payload.data_len =
833 sizeof(((union i3c_ccc_getmxds *)0)->fmt3.crhdly1);
834 break;
835 default:
836 ret = -EINVAL;
837 goto out;
838 }
839 } else {
840 ret = -EINVAL;
841 goto out;
842 }
843
844 memset(&ccc_payload, 0, sizeof(ccc_payload));
845 ccc_payload.ccc.id = I3C_CCC_GETMXDS;
846 ccc_payload.targets.payloads = &ccc_tgt_payload;
847 ccc_payload.targets.num_targets = 1;
848
849 if (fmt == GETMXDS_FORMAT_3) {
850 defining_byte = (uint8_t)defbyte;
851
852 ccc_payload.ccc.data = &defining_byte;
853 ccc_payload.ccc.data_len = 1;
854 }
855
856 ret = i3c_do_ccc(target->bus, &ccc_payload);
857
858 if (ret == 0) {
859 /* GETMXDS will return a variable length */
860 len = ccc_tgt_payload.num_xfer;
861
862 if ((fmt == GETMXDS_FORMAT_1) || (fmt == GETMXDS_FORMAT_2)) {
863 if (len == sizeof(((union i3c_ccc_getmxds *)0)->fmt1)) {
864 mxds->fmt1.maxwr = data[0];
865 mxds->fmt1.maxrd = data[1];
866 /* It is unknown wither format 1 or format 2 is returned ahead of
867 * time
868 */
869 memset(&mxds->fmt2.maxrdturn, 0, sizeof(mxds->fmt2.maxrdturn));
870 } else if (len == sizeof(((union i3c_ccc_getmxds *)0)->fmt2)) {
871 mxds->fmt2.maxwr = data[0];
872 mxds->fmt2.maxrd = data[1];
873 memcpy(&mxds->fmt2.maxrdturn, &data[2],
874 sizeof(mxds->fmt2.maxrdturn));
875 }
876 } else if (fmt == GETMXDS_FORMAT_3) {
877 switch (defbyte) {
878 case GETMXDS_FORMAT_3_WRRDTURN:
879 memcpy(mxds->fmt3.wrrdturn, data, len);
880 /* for values not received, assume default (1'b0) */
881 memset(&mxds->fmt3.wrrdturn[len], 0,
882 sizeof(mxds->fmt3.wrrdturn) - len);
883 break;
884 case GETMXDS_FORMAT_3_CRHDLY:
885 mxds->fmt3.crhdly1 = data[0];
886 break;
887 default:
888 break;
889 }
890 }
891 }
892
893 out:
894 return ret;
895 }
896
i3c_ccc_do_setbuscon(const struct device * controller,uint8_t * context,uint16_t length)897 int i3c_ccc_do_setbuscon(const struct device *controller,
898 uint8_t *context, uint16_t length)
899 {
900 struct i3c_ccc_payload ccc_payload;
901
902 __ASSERT_NO_MSG(controller != NULL);
903 __ASSERT_NO_MSG(context != NULL);
904
905 memset(&ccc_payload, 0, sizeof(ccc_payload));
906 ccc_payload.ccc.id = I3C_CCC_SETBUSCON;
907
908 ccc_payload.ccc.data = context;
909 ccc_payload.ccc.data_len = length;
910
911 return i3c_do_ccc(controller, &ccc_payload);
912 }
913