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 ccc_tgt_payload.data_len = 0;
259
260 ccc_payload.ccc.id = I3C_CCC_ENTAS(as, false);
261 ccc_payload.targets.payloads = &ccc_tgt_payload;
262 ccc_payload.targets.num_targets = 1;
263
264 return i3c_do_ccc(target->bus, &ccc_payload);
265 }
266
i3c_ccc_do_entas_all(const struct device * controller,uint8_t as)267 int i3c_ccc_do_entas_all(const struct device *controller, uint8_t as)
268 {
269 struct i3c_ccc_payload ccc_payload;
270
271 __ASSERT_NO_MSG(controller != NULL);
272 __ASSERT_NO_MSG(as <= 3);
273
274 memset(&ccc_payload, 0, sizeof(ccc_payload));
275 ccc_payload.ccc.id = I3C_CCC_ENTAS(as, true);
276
277 return i3c_do_ccc(controller, &ccc_payload);
278 }
279
i3c_ccc_do_setmwl_all(const struct device * controller,const struct i3c_ccc_mwl * mwl)280 int i3c_ccc_do_setmwl_all(const struct device *controller,
281 const struct i3c_ccc_mwl *mwl)
282 {
283 struct i3c_ccc_payload ccc_payload;
284 uint8_t data[2];
285
286 __ASSERT_NO_MSG(controller != NULL);
287
288 memset(&ccc_payload, 0, sizeof(ccc_payload));
289
290 ccc_payload.ccc.id = I3C_CCC_SETMWL(true);
291
292 ccc_payload.ccc.data = &data[0];
293 ccc_payload.ccc.data_len = sizeof(data);
294
295 /* The actual data is MSB first. So order the data. */
296 sys_put_be16(mwl->len, data);
297
298 return i3c_do_ccc(controller, &ccc_payload);
299 }
300
i3c_ccc_do_setmwl(const struct i3c_device_desc * target,const struct i3c_ccc_mwl * mwl)301 int i3c_ccc_do_setmwl(const struct i3c_device_desc *target,
302 const struct i3c_ccc_mwl *mwl)
303 {
304 struct i3c_ccc_payload ccc_payload;
305 struct i3c_ccc_target_payload ccc_tgt_payload;
306 uint8_t data[2];
307
308 __ASSERT_NO_MSG(target != NULL);
309 __ASSERT_NO_MSG(target->bus != NULL);
310
311 memset(&ccc_payload, 0, sizeof(ccc_payload));
312
313 ccc_tgt_payload.addr = target->dynamic_addr;
314 ccc_tgt_payload.rnw = 0;
315 ccc_tgt_payload.data = &data[0];
316 ccc_tgt_payload.data_len = sizeof(data);
317
318 ccc_payload.ccc.id = I3C_CCC_SETMWL(false);
319 ccc_payload.targets.payloads = &ccc_tgt_payload;
320 ccc_payload.targets.num_targets = 1;
321
322 /* The actual length is MSB first. So order the data. */
323 sys_put_be16(mwl->len, data);
324
325 return i3c_do_ccc(target->bus, &ccc_payload);
326 }
327
i3c_ccc_do_getmwl(const struct i3c_device_desc * target,struct i3c_ccc_mwl * mwl)328 int i3c_ccc_do_getmwl(const struct i3c_device_desc *target,
329 struct i3c_ccc_mwl *mwl)
330 {
331 struct i3c_ccc_payload ccc_payload;
332 struct i3c_ccc_target_payload ccc_tgt_payload;
333 uint8_t data[2];
334 int ret;
335
336 __ASSERT_NO_MSG(target != NULL);
337 __ASSERT_NO_MSG(target->bus != NULL);
338 __ASSERT_NO_MSG(mwl != NULL);
339
340 ccc_tgt_payload.addr = target->dynamic_addr;
341 ccc_tgt_payload.rnw = 1;
342 ccc_tgt_payload.data = &data[0];
343 ccc_tgt_payload.data_len = sizeof(data);
344
345 memset(&ccc_payload, 0, sizeof(ccc_payload));
346 ccc_payload.ccc.id = I3C_CCC_GETMWL;
347 ccc_payload.targets.payloads = &ccc_tgt_payload;
348 ccc_payload.targets.num_targets = 1;
349
350 ret = i3c_do_ccc(target->bus, &ccc_payload);
351
352 if (ret == 0) {
353 /* The actual length is MSB first. So order the data. */
354 mwl->len = sys_get_be16(data);
355 }
356
357 return ret;
358 }
359
i3c_ccc_do_setmrl_all(const struct device * controller,const struct i3c_ccc_mrl * mrl,bool has_ibi_size)360 int i3c_ccc_do_setmrl_all(const struct device *controller,
361 const struct i3c_ccc_mrl *mrl,
362 bool has_ibi_size)
363 {
364 struct i3c_ccc_payload ccc_payload;
365 uint8_t data[3];
366
367 __ASSERT_NO_MSG(controller != NULL);
368
369 memset(&ccc_payload, 0, sizeof(ccc_payload));
370
371 ccc_payload.ccc.id = I3C_CCC_SETMRL(true);
372
373 ccc_payload.ccc.data = &data[0];
374 ccc_payload.ccc.data_len = has_ibi_size ? 3 : 2;
375
376 /* The actual length is MSB first. So order the data. */
377 sys_put_be16(mrl->len, data);
378
379 if (has_ibi_size) {
380 data[2] = mrl->ibi_len;
381 }
382
383 return i3c_do_ccc(controller, &ccc_payload);
384 }
385
i3c_ccc_do_setmrl(const struct i3c_device_desc * target,const struct i3c_ccc_mrl * mrl)386 int i3c_ccc_do_setmrl(const struct i3c_device_desc *target,
387 const 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
393 __ASSERT_NO_MSG(target != NULL);
394 __ASSERT_NO_MSG(target->bus != NULL);
395
396 memset(&ccc_payload, 0, sizeof(ccc_payload));
397
398 ccc_tgt_payload.addr = target->dynamic_addr;
399 ccc_tgt_payload.rnw = 0;
400 ccc_tgt_payload.data = &data[0];
401
402 ccc_payload.ccc.id = I3C_CCC_SETMRL(false);
403 ccc_payload.targets.payloads = &ccc_tgt_payload;
404 ccc_payload.targets.num_targets = 1;
405
406 /* The actual length is MSB first. So order the data. */
407 sys_put_be16(mrl->len, data);
408
409 if ((target->bcr & I3C_BCR_IBI_PAYLOAD_HAS_DATA_BYTE)
410 == I3C_BCR_IBI_PAYLOAD_HAS_DATA_BYTE) {
411 ccc_tgt_payload.data_len = 3;
412
413 data[2] = mrl->ibi_len;
414 } else {
415 ccc_tgt_payload.data_len = 2;
416 }
417
418 return i3c_do_ccc(target->bus, &ccc_payload);
419 }
420
i3c_ccc_do_getmrl(const struct i3c_device_desc * target,struct i3c_ccc_mrl * mrl)421 int i3c_ccc_do_getmrl(const struct i3c_device_desc *target,
422 struct i3c_ccc_mrl *mrl)
423 {
424 struct i3c_ccc_payload ccc_payload;
425 struct i3c_ccc_target_payload ccc_tgt_payload;
426 uint8_t data[3];
427 bool has_ibi_sz;
428 int ret;
429
430 __ASSERT_NO_MSG(target != NULL);
431 __ASSERT_NO_MSG(target->bus != NULL);
432 __ASSERT_NO_MSG(mrl != NULL);
433
434 has_ibi_sz = (target->bcr & I3C_BCR_IBI_PAYLOAD_HAS_DATA_BYTE)
435 == I3C_BCR_IBI_PAYLOAD_HAS_DATA_BYTE;
436
437 ccc_tgt_payload.addr = target->dynamic_addr;
438 ccc_tgt_payload.rnw = 1;
439 ccc_tgt_payload.data = &data[0];
440 ccc_tgt_payload.data_len = has_ibi_sz ? 3 : 2;
441
442 memset(&ccc_payload, 0, sizeof(ccc_payload));
443 ccc_payload.ccc.id = I3C_CCC_GETMRL;
444 ccc_payload.targets.payloads = &ccc_tgt_payload;
445 ccc_payload.targets.num_targets = 1;
446
447 ret = i3c_do_ccc(target->bus, &ccc_payload);
448
449 if (ret == 0) {
450 /* The actual length is MSB first. So order the data. */
451 mrl->len = sys_get_be16(data);
452
453 if (has_ibi_sz) {
454 mrl->ibi_len = data[2];
455 }
456 }
457
458 return ret;
459 }
460
i3c_ccc_do_enttm(const struct device * controller,enum i3c_ccc_enttm_defbyte defbyte)461 int i3c_ccc_do_enttm(const struct device *controller,
462 enum i3c_ccc_enttm_defbyte defbyte)
463 {
464 struct i3c_ccc_payload ccc_payload;
465 uint8_t def_byte;
466
467 __ASSERT_NO_MSG(controller != NULL);
468
469 memset(&ccc_payload, 0, sizeof(ccc_payload));
470 ccc_payload.ccc.id = I3C_CCC_ENTTM;
471
472 def_byte = (uint8_t)defbyte;
473 ccc_payload.ccc.data = &def_byte;
474 ccc_payload.ccc.data_len = 1U;
475
476 return i3c_do_ccc(controller, &ccc_payload);
477 }
478
i3c_ccc_do_deftgts_all(const struct device * controller,struct i3c_ccc_deftgts * deftgts)479 int i3c_ccc_do_deftgts_all(const struct device *controller,
480 struct i3c_ccc_deftgts *deftgts)
481 {
482 struct i3c_ccc_payload ccc_payload;
483
484 __ASSERT_NO_MSG(controller != NULL);
485 __ASSERT_NO_MSG(deftgts != NULL);
486
487 memset(&ccc_payload, 0, sizeof(ccc_payload));
488 ccc_payload.ccc.id = I3C_CCC_DEFTGTS;
489
490 ccc_payload.ccc.data = (uint8_t *)deftgts;
491 ccc_payload.ccc.data_len = sizeof(uint8_t) +
492 sizeof(struct i3c_ccc_deftgts_active_controller) +
493 (deftgts->count * sizeof(struct i3c_ccc_deftgts_target));
494
495 return i3c_do_ccc(controller, &ccc_payload);
496 }
497
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)498 int i3c_ccc_do_getstatus(const struct i3c_device_desc *target,
499 union i3c_ccc_getstatus *status,
500 enum i3c_ccc_getstatus_fmt fmt,
501 enum i3c_ccc_getstatus_defbyte defbyte)
502 {
503 struct i3c_ccc_payload ccc_payload;
504 struct i3c_ccc_target_payload ccc_tgt_payload;
505 uint8_t defining_byte;
506 uint8_t data[2];
507 int ret;
508
509 __ASSERT_NO_MSG(target != NULL);
510 __ASSERT_NO_MSG(target->bus != NULL);
511 __ASSERT_NO_MSG(status != NULL);
512
513 ccc_tgt_payload.addr = target->dynamic_addr;
514 ccc_tgt_payload.rnw = 1;
515 ccc_tgt_payload.data = &data[0];
516
517 if (fmt == GETSTATUS_FORMAT_1) {
518 ccc_tgt_payload.data_len = 2;
519 } else if (fmt == GETSTATUS_FORMAT_2) {
520 switch (defbyte) {
521 case GETSTATUS_FORMAT_2_TGTSTAT:
522 __fallthrough;
523 case GETSTATUS_FORMAT_2_PRECR:
524 ccc_tgt_payload.data_len = 2;
525 break;
526 default:
527 ret = -EINVAL;
528 goto out;
529 }
530 } else {
531 ret = -EINVAL;
532 goto out;
533 }
534
535 memset(&ccc_payload, 0, sizeof(ccc_payload));
536 ccc_payload.ccc.id = I3C_CCC_GETSTATUS;
537 ccc_payload.targets.payloads = &ccc_tgt_payload;
538 ccc_payload.targets.num_targets = 1;
539
540 if (fmt == GETSTATUS_FORMAT_2) {
541 defining_byte = (uint8_t)defbyte;
542
543 ccc_payload.ccc.data = &defining_byte;
544 ccc_payload.ccc.data_len = 1;
545 }
546
547 ret = i3c_do_ccc(target->bus, &ccc_payload);
548
549 if (ret == 0) {
550 /* Received data is MSB first. So order the data. */
551 if (fmt == GETSTATUS_FORMAT_1) {
552 status->fmt1.status = sys_get_be16(data);
553 } else if (fmt == GETSTATUS_FORMAT_2) {
554 switch (defbyte) {
555 case GETSTATUS_FORMAT_2_TGTSTAT:
556 __fallthrough;
557 case GETSTATUS_FORMAT_2_PRECR:
558 status->fmt2.raw_u16 = sys_get_be16(data);
559 break;
560 default:
561 break;
562 }
563 }
564 }
565
566 out:
567 return ret;
568 }
569
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)570 int i3c_ccc_do_getcaps(const struct i3c_device_desc *target,
571 union i3c_ccc_getcaps *caps,
572 enum i3c_ccc_getcaps_fmt fmt,
573 enum i3c_ccc_getcaps_defbyte defbyte)
574 {
575 struct i3c_ccc_payload ccc_payload;
576 struct i3c_ccc_target_payload ccc_tgt_payload;
577 uint8_t defining_byte;
578 uint8_t data[4];
579 uint8_t len;
580 int ret;
581
582 __ASSERT_NO_MSG(target != NULL);
583 __ASSERT_NO_MSG(target->bus != NULL);
584 __ASSERT_NO_MSG(caps != NULL);
585
586 ccc_tgt_payload.addr = target->dynamic_addr;
587 ccc_tgt_payload.rnw = 1;
588 ccc_tgt_payload.data = &data[0];
589
590 if (fmt == GETCAPS_FORMAT_1) {
591 /* Could be 1-4 Data Bytes Returned */
592 ccc_tgt_payload.data_len = 4;
593 } else if (fmt == GETCAPS_FORMAT_2) {
594 switch (defbyte) {
595 case GETCAPS_FORMAT_2_CRCAPS:
596 __fallthrough;
597 case GETCAPS_FORMAT_2_VTCAPS:
598 /* Could be 1-2 Data Bytes Returned*/
599 ccc_tgt_payload.data_len = 2;
600 break;
601 case GETCAPS_FORMAT_2_TGTCAPS:
602 __fallthrough;
603 case GETCAPS_FORMAT_2_TESTPAT:
604 /* Could be 1-4 Data Bytes Returned */
605 ccc_tgt_payload.data_len = 4;
606 break;
607 default:
608 ret = -EINVAL;
609 goto out;
610 }
611 } else {
612 ret = -EINVAL;
613 goto out;
614 }
615
616 memset(&ccc_payload, 0, sizeof(ccc_payload));
617 ccc_payload.ccc.id = I3C_CCC_GETCAPS;
618 ccc_payload.targets.payloads = &ccc_tgt_payload;
619 ccc_payload.targets.num_targets = 1;
620
621 if (fmt == GETCAPS_FORMAT_2) {
622 defining_byte = (uint8_t)defbyte;
623
624 ccc_payload.ccc.data = &defining_byte;
625 ccc_payload.ccc.data_len = 1;
626 }
627
628 ret = i3c_do_ccc(target->bus, &ccc_payload);
629
630 if (ret == 0) {
631 /* GETCAPS will return a variable length */
632 len = ccc_tgt_payload.num_xfer;
633
634 if (fmt == GETCAPS_FORMAT_1) {
635 memcpy(caps->fmt1.getcaps, data, len);
636 /* for values not received, assume default (1'b0) */
637 memset(&caps->fmt1.getcaps[len], 0, sizeof(caps->fmt1.getcaps) - len);
638 } else if (fmt == GETCAPS_FORMAT_2) {
639 switch (defbyte) {
640 case GETCAPS_FORMAT_2_CRCAPS:
641 memcpy(caps->fmt2.crcaps, data, len);
642 /* for values not received, assume default (1'b0) */
643 memset(&caps->fmt2.crcaps[len], 0, sizeof(caps->fmt2.crcaps) - len);
644 break;
645 case GETCAPS_FORMAT_2_VTCAPS:
646 memcpy(caps->fmt2.vtcaps, data, len);
647 /* for values not received, assume default (1'b0) */
648 memset(&caps->fmt2.vtcaps[len], 0, sizeof(caps->fmt2.vtcaps) - len);
649 break;
650 case GETCAPS_FORMAT_2_TGTCAPS:
651 memcpy(caps->fmt2.tgtcaps, data, len);
652 /* for values not received, assume default (1'b0) */
653 memset(&caps->fmt2.tgtcaps[len], 0,
654 sizeof(caps->fmt2.tgtcaps) - len);
655 break;
656 case GETCAPS_FORMAT_2_TESTPAT:
657 /* should always be 4 data bytes */
658 caps->fmt2.testpat = sys_get_be32(data);
659 break;
660 default:
661 break;
662 }
663 }
664 }
665
666 out:
667 return ret;
668 }
669
i3c_ccc_do_setvendor(const struct i3c_device_desc * target,uint8_t id,uint8_t * payload,size_t len)670 int i3c_ccc_do_setvendor(const struct i3c_device_desc *target,
671 uint8_t id,
672 uint8_t *payload,
673 size_t len)
674 {
675 struct i3c_ccc_payload ccc_payload;
676
677 __ASSERT_NO_MSG(target != NULL);
678
679 /* CCC must be between 0xE0 and 0xFE, the total range of this is 0x1E */
680 if (id > 0x1E) {
681 return -EINVAL;
682 }
683
684 memset(&ccc_payload, 0, sizeof(ccc_payload));
685 ccc_payload.ccc.id = I3C_CCC_VENDOR(false, id);
686 ccc_payload.ccc.data = payload;
687 ccc_payload.ccc.data_len = len;
688
689 return i3c_do_ccc(target->bus, &ccc_payload);
690 }
691
i3c_ccc_do_getvendor(const struct i3c_device_desc * target,uint8_t id,uint8_t * payload,size_t len,size_t * num_xfer)692 int i3c_ccc_do_getvendor(const struct i3c_device_desc *target,
693 uint8_t id,
694 uint8_t *payload,
695 size_t len,
696 size_t *num_xfer)
697 {
698 struct i3c_ccc_payload ccc_payload;
699 struct i3c_ccc_target_payload ccc_tgt_payload;
700 int ret;
701
702 __ASSERT_NO_MSG(target != NULL);
703
704 /* CCC must be between 0xE0 and 0xFE, the total range of this is 0x1E */
705 if (id > 0x1E) {
706 return -EINVAL;
707 }
708
709 ccc_tgt_payload.addr = target->dynamic_addr;
710 ccc_tgt_payload.rnw = 1;
711 ccc_tgt_payload.data = payload;
712 ccc_tgt_payload.data_len = len;
713
714 memset(&ccc_payload, 0, sizeof(ccc_payload));
715 ccc_payload.ccc.id = I3C_CCC_VENDOR(false, id);
716 ccc_payload.targets.payloads = &ccc_tgt_payload;
717 ccc_payload.targets.num_targets = 1;
718
719 ret = i3c_do_ccc(target->bus, &ccc_payload);
720
721 if (ret == 0) {
722 *num_xfer = ccc_tgt_payload.num_xfer;
723 }
724
725 return ret;
726 }
727
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)728 int i3c_ccc_do_getvendor_defbyte(const struct i3c_device_desc *target,
729 uint8_t id,
730 uint8_t defbyte,
731 uint8_t *payload,
732 size_t len,
733 size_t *num_xfer)
734 {
735 struct i3c_ccc_payload ccc_payload;
736 struct i3c_ccc_target_payload ccc_tgt_payload;
737 int ret;
738
739 __ASSERT_NO_MSG(target != NULL);
740
741 /* CCC must be between 0xE0 and 0xFE, the total range of this is 0x1E */
742 if (id > 0x1E) {
743 return -EINVAL;
744 }
745
746 ccc_tgt_payload.addr = target->dynamic_addr;
747 ccc_tgt_payload.rnw = 1;
748 ccc_tgt_payload.data = payload;
749 ccc_tgt_payload.data_len = len;
750
751 memset(&ccc_payload, 0, sizeof(ccc_payload));
752 ccc_payload.ccc.id = I3C_CCC_VENDOR(false, id);
753 ccc_payload.ccc.data = &defbyte;
754 ccc_payload.ccc.data_len = 1;
755 ccc_payload.targets.payloads = &ccc_tgt_payload;
756 ccc_payload.targets.num_targets = 1;
757
758 ret = i3c_do_ccc(target->bus, &ccc_payload);
759
760 if (ret == 0) {
761 *num_xfer = ccc_tgt_payload.num_xfer;
762 }
763
764 return ret;
765 }
766
i3c_ccc_do_setvendor_all(const struct device * controller,uint8_t id,uint8_t * payload,size_t len)767 int i3c_ccc_do_setvendor_all(const struct device *controller,
768 uint8_t id,
769 uint8_t *payload,
770 size_t len)
771 {
772 struct i3c_ccc_payload ccc_payload;
773
774 __ASSERT_NO_MSG(controller != NULL);
775
776 /* CCC must be between 0x61 and 0x7F, the total range of this is 0x1E */
777 if (id > 0x1E) {
778 return -EINVAL;
779 }
780
781 memset(&ccc_payload, 0, sizeof(ccc_payload));
782 ccc_payload.ccc.id = I3C_CCC_VENDOR(true, id);
783 ccc_payload.ccc.data = payload;
784 ccc_payload.ccc.data_len = len;
785
786 return i3c_do_ccc(controller, &ccc_payload);
787 }
788
i3c_ccc_do_setaasa_all(const struct device * controller)789 int i3c_ccc_do_setaasa_all(const struct device *controller)
790 {
791 struct i3c_ccc_payload ccc_payload;
792
793 __ASSERT_NO_MSG(controller != NULL);
794
795 memset(&ccc_payload, 0, sizeof(ccc_payload));
796 ccc_payload.ccc.id = I3C_CCC_SETAASA;
797
798 return i3c_do_ccc(controller, &ccc_payload);
799 }
800
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)801 int i3c_ccc_do_getmxds(const struct i3c_device_desc *target,
802 union i3c_ccc_getmxds *mxds,
803 enum i3c_ccc_getmxds_fmt fmt,
804 enum i3c_ccc_getmxds_defbyte defbyte)
805 {
806 struct i3c_ccc_payload ccc_payload;
807 struct i3c_ccc_target_payload ccc_tgt_payload;
808 uint8_t defining_byte;
809 uint8_t data[5];
810 uint8_t len;
811 int ret;
812
813 __ASSERT_NO_MSG(target != NULL);
814 __ASSERT_NO_MSG(target->bus != NULL);
815 __ASSERT_NO_MSG(mxds != NULL);
816
817 ccc_tgt_payload.addr = target->dynamic_addr;
818 ccc_tgt_payload.rnw = 1;
819 ccc_tgt_payload.data = &data[0];
820
821 if ((fmt == GETMXDS_FORMAT_1) || (fmt == GETMXDS_FORMAT_2)) {
822 /* Could be 2 or 5 Data Bytes Returned */
823 ccc_tgt_payload.data_len = sizeof(((union i3c_ccc_getmxds *)0)->fmt2);
824 } else if (fmt == GETMXDS_FORMAT_3) {
825 switch (defbyte) {
826 case GETMXDS_FORMAT_3_WRRDTURN:
827 /* Could be 2 or 5 Data Bytes Returned */
828 ccc_tgt_payload.data_len =
829 sizeof(((union i3c_ccc_getmxds *)0)->fmt3.wrrdturn);
830 break;
831 case GETMXDS_FORMAT_3_CRHDLY:
832 /* Only 1 Byte returned */
833 ccc_tgt_payload.data_len =
834 sizeof(((union i3c_ccc_getmxds *)0)->fmt3.crhdly1);
835 break;
836 default:
837 ret = -EINVAL;
838 goto out;
839 }
840 } else {
841 ret = -EINVAL;
842 goto out;
843 }
844
845 memset(&ccc_payload, 0, sizeof(ccc_payload));
846 ccc_payload.ccc.id = I3C_CCC_GETMXDS;
847 ccc_payload.targets.payloads = &ccc_tgt_payload;
848 ccc_payload.targets.num_targets = 1;
849
850 if (fmt == GETMXDS_FORMAT_3) {
851 defining_byte = (uint8_t)defbyte;
852
853 ccc_payload.ccc.data = &defining_byte;
854 ccc_payload.ccc.data_len = 1;
855 }
856
857 ret = i3c_do_ccc(target->bus, &ccc_payload);
858
859 if (ret == 0) {
860 /* GETMXDS will return a variable length */
861 len = ccc_tgt_payload.num_xfer;
862
863 if ((fmt == GETMXDS_FORMAT_1) || (fmt == GETMXDS_FORMAT_2)) {
864 if (len == SIZEOF_FIELD(union i3c_ccc_getmxds, fmt1)) {
865 mxds->fmt1.maxwr = data[0];
866 mxds->fmt1.maxrd = data[1];
867 /* It is unknown wither format 1 or format 2 is returned ahead of
868 * time
869 */
870 memset(&mxds->fmt2.maxrdturn, 0, sizeof(mxds->fmt2.maxrdturn));
871 } else if (len == SIZEOF_FIELD(union i3c_ccc_getmxds, fmt2)) {
872 mxds->fmt2.maxwr = data[0];
873 mxds->fmt2.maxrd = data[1];
874 memcpy(&mxds->fmt2.maxrdturn, &data[2],
875 sizeof(mxds->fmt2.maxrdturn));
876 }
877 } else if (fmt == GETMXDS_FORMAT_3) {
878 switch (defbyte) {
879 case GETMXDS_FORMAT_3_WRRDTURN:
880 memcpy(mxds->fmt3.wrrdturn, data, len);
881 /* for values not received, assume default (1'b0) */
882 memset(&mxds->fmt3.wrrdturn[len], 0,
883 sizeof(mxds->fmt3.wrrdturn) - len);
884 break;
885 case GETMXDS_FORMAT_3_CRHDLY:
886 mxds->fmt3.crhdly1 = data[0];
887 break;
888 default:
889 break;
890 }
891 }
892 }
893
894 out:
895 return ret;
896 }
897
i3c_ccc_do_setbuscon(const struct device * controller,uint8_t * context,uint16_t length)898 int i3c_ccc_do_setbuscon(const struct device *controller,
899 uint8_t *context, uint16_t length)
900 {
901 struct i3c_ccc_payload ccc_payload;
902
903 __ASSERT_NO_MSG(controller != NULL);
904 __ASSERT_NO_MSG(context != NULL);
905
906 memset(&ccc_payload, 0, sizeof(ccc_payload));
907 ccc_payload.ccc.id = I3C_CCC_SETBUSCON;
908
909 ccc_payload.ccc.data = context;
910 ccc_payload.ccc.data_len = length;
911
912 return i3c_do_ccc(controller, &ccc_payload);
913 }
914
i3c_ccc_do_getacccr(const struct i3c_device_desc * target,struct i3c_ccc_address * handoff_address)915 int i3c_ccc_do_getacccr(const struct i3c_device_desc *target,
916 struct i3c_ccc_address *handoff_address)
917 {
918 struct i3c_ccc_payload ccc_payload;
919 struct i3c_ccc_target_payload ccc_tgt_payload;
920 int ret;
921
922 __ASSERT_NO_MSG(target != NULL);
923 __ASSERT_NO_MSG(handoff_address != NULL);
924
925 ccc_tgt_payload.addr = target->dynamic_addr;
926 ccc_tgt_payload.rnw = 1;
927 ccc_tgt_payload.data = &handoff_address->addr;
928 ccc_tgt_payload.data_len = 1;
929
930 memset(&ccc_payload, 0, sizeof(ccc_payload));
931 ccc_payload.ccc.id = I3C_CCC_GETACCCR;
932 ccc_payload.targets.payloads = &ccc_tgt_payload;
933 ccc_payload.targets.num_targets = 1;
934
935 ret = i3c_do_ccc(target->bus, &ccc_payload);
936
937 return ret;
938 }
939