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_rstdaa_all(const struct device * controller)105 int i3c_ccc_do_rstdaa_all(const struct device *controller)
106 {
107 struct i3c_ccc_payload ccc_payload;
108
109 __ASSERT_NO_MSG(controller != NULL);
110
111 memset(&ccc_payload, 0, sizeof(ccc_payload));
112 ccc_payload.ccc.id = I3C_CCC_RSTDAA;
113
114 return i3c_do_ccc(controller, &ccc_payload);
115 }
116
i3c_ccc_do_setdasa(const struct i3c_device_desc * target)117 int i3c_ccc_do_setdasa(const struct i3c_device_desc *target)
118 {
119 struct i3c_driver_data *bus_data = (struct i3c_driver_data *)target->bus->data;
120 struct i3c_ccc_payload ccc_payload;
121 struct i3c_ccc_target_payload ccc_tgt_payload;
122 uint8_t dyn_addr;
123
124 __ASSERT_NO_MSG(target != NULL);
125 __ASSERT_NO_MSG(target->bus != NULL);
126
127 if ((target->static_addr == 0U) || (target->dynamic_addr != 0U)) {
128 return -EINVAL;
129 }
130
131 /*
132 * Note that the 7-bit address needs to start at bit 1
133 * (aka left-justified). So shift left by 1;
134 */
135 dyn_addr = (target->init_dynamic_addr ?
136 target->init_dynamic_addr : target->static_addr) << 1;
137
138 /* check that initial dynamic address is free before setting it */
139 if ((target->init_dynamic_addr != 0) &&
140 (target->init_dynamic_addr != target->static_addr)) {
141 if (!i3c_addr_slots_is_free(&bus_data->attached_dev.addr_slots, dyn_addr >> 1)) {
142 return -EINVAL;
143 }
144 }
145
146 ccc_tgt_payload.addr = target->static_addr;
147 ccc_tgt_payload.rnw = 0;
148 ccc_tgt_payload.data = &dyn_addr;
149 ccc_tgt_payload.data_len = 1;
150
151 memset(&ccc_payload, 0, sizeof(ccc_payload));
152 ccc_payload.ccc.id = I3C_CCC_SETDASA;
153 ccc_payload.targets.payloads = &ccc_tgt_payload;
154 ccc_payload.targets.num_targets = 1;
155
156 return i3c_do_ccc(target->bus, &ccc_payload);
157 }
158
i3c_ccc_do_setnewda(const struct i3c_device_desc * target,struct i3c_ccc_address new_da)159 int i3c_ccc_do_setnewda(const struct i3c_device_desc *target, struct i3c_ccc_address new_da)
160 {
161 struct i3c_driver_data *bus_data = (struct i3c_driver_data *)target->bus->data;
162 struct i3c_ccc_payload ccc_payload;
163 struct i3c_ccc_target_payload ccc_tgt_payload;
164 uint8_t new_dyn_addr;
165
166 __ASSERT_NO_MSG(target != NULL);
167 __ASSERT_NO_MSG(target->bus != NULL);
168
169 if (target->dynamic_addr == 0U) {
170 return -EINVAL;
171 }
172
173 /*
174 * Note that the 7-bit address needs to start at bit 1
175 * (aka left-justified). So shift left by 1;
176 */
177 new_dyn_addr = new_da.addr << 1;
178
179 /* check that initial dynamic address is free before setting it */
180 if (target->dynamic_addr != new_da.addr) {
181 if (!i3c_addr_slots_is_free(&bus_data->attached_dev.addr_slots, new_da.addr)) {
182 return -EINVAL;
183 }
184 }
185
186 ccc_tgt_payload.addr = target->dynamic_addr;
187 ccc_tgt_payload.rnw = 0;
188 ccc_tgt_payload.data = &new_dyn_addr;
189 ccc_tgt_payload.data_len = 1;
190
191 memset(&ccc_payload, 0, sizeof(ccc_payload));
192 ccc_payload.ccc.id = I3C_CCC_SETNEWDA;
193 ccc_payload.targets.payloads = &ccc_tgt_payload;
194 ccc_payload.targets.num_targets = 1;
195
196 return i3c_do_ccc(target->bus, &ccc_payload);
197 }
198
i3c_ccc_do_events_all_set(const struct device * controller,bool enable,struct i3c_ccc_events * events)199 int i3c_ccc_do_events_all_set(const struct device *controller,
200 bool enable, struct i3c_ccc_events *events)
201 {
202 struct i3c_ccc_payload ccc_payload;
203
204 __ASSERT_NO_MSG(controller != NULL);
205
206 memset(&ccc_payload, 0, sizeof(ccc_payload));
207
208 ccc_payload.ccc.id = enable ? I3C_CCC_ENEC(true) : I3C_CCC_DISEC(true);
209
210 ccc_payload.ccc.data = &events->events;
211 ccc_payload.ccc.data_len = sizeof(events->events);
212
213 return i3c_do_ccc(controller, &ccc_payload);
214 }
215
i3c_ccc_do_events_set(struct i3c_device_desc * target,bool enable,struct i3c_ccc_events * events)216 int i3c_ccc_do_events_set(struct i3c_device_desc *target,
217 bool enable, struct i3c_ccc_events *events)
218 {
219 struct i3c_ccc_payload ccc_payload;
220 struct i3c_ccc_target_payload ccc_tgt_payload;
221
222 __ASSERT_NO_MSG(target != NULL);
223 __ASSERT_NO_MSG(target->bus != NULL);
224
225 if (target->dynamic_addr == 0U) {
226 return -EINVAL;
227 }
228
229 ccc_tgt_payload.addr = target->dynamic_addr;
230 ccc_tgt_payload.rnw = 0;
231 ccc_tgt_payload.data = &events->events;
232 ccc_tgt_payload.data_len = sizeof(events->events);
233
234 memset(&ccc_payload, 0, sizeof(ccc_payload));
235 ccc_payload.ccc.id = enable ? I3C_CCC_ENEC(false) : I3C_CCC_DISEC(false);
236 ccc_payload.targets.payloads = &ccc_tgt_payload;
237 ccc_payload.targets.num_targets = 1;
238
239 return i3c_do_ccc(target->bus, &ccc_payload);
240 }
241
i3c_ccc_do_setmwl_all(const struct device * controller,const struct i3c_ccc_mwl * mwl)242 int i3c_ccc_do_setmwl_all(const struct device *controller,
243 const struct i3c_ccc_mwl *mwl)
244 {
245 struct i3c_ccc_payload ccc_payload;
246 uint8_t data[2];
247
248 __ASSERT_NO_MSG(controller != NULL);
249
250 memset(&ccc_payload, 0, sizeof(ccc_payload));
251
252 ccc_payload.ccc.id = I3C_CCC_SETMWL(true);
253
254 ccc_payload.ccc.data = &data[0];
255 ccc_payload.ccc.data_len = sizeof(data);
256
257 /* The actual data is MSB first. So order the data. */
258 sys_put_be16(mwl->len, data);
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 sys_put_be16(mwl->len, data);
286
287 return i3c_do_ccc(target->bus, &ccc_payload);
288 }
289
i3c_ccc_do_getmwl(const struct i3c_device_desc * target,struct i3c_ccc_mwl * mwl)290 int i3c_ccc_do_getmwl(const struct i3c_device_desc *target,
291 struct i3c_ccc_mwl *mwl)
292 {
293 struct i3c_ccc_payload ccc_payload;
294 struct i3c_ccc_target_payload ccc_tgt_payload;
295 uint8_t data[2];
296 int ret;
297
298 __ASSERT_NO_MSG(target != NULL);
299 __ASSERT_NO_MSG(target->bus != NULL);
300 __ASSERT_NO_MSG(mwl != NULL);
301
302 ccc_tgt_payload.addr = target->dynamic_addr;
303 ccc_tgt_payload.rnw = 1;
304 ccc_tgt_payload.data = &data[0];
305 ccc_tgt_payload.data_len = sizeof(data);
306
307 memset(&ccc_payload, 0, sizeof(ccc_payload));
308 ccc_payload.ccc.id = I3C_CCC_GETMWL;
309 ccc_payload.targets.payloads = &ccc_tgt_payload;
310 ccc_payload.targets.num_targets = 1;
311
312 ret = i3c_do_ccc(target->bus, &ccc_payload);
313
314 if (ret == 0) {
315 /* The actual length is MSB first. So order the data. */
316 mwl->len = sys_get_be16(data);
317 }
318
319 return ret;
320 }
321
i3c_ccc_do_setmrl_all(const struct device * controller,const struct i3c_ccc_mrl * mrl,bool has_ibi_size)322 int i3c_ccc_do_setmrl_all(const struct device *controller,
323 const struct i3c_ccc_mrl *mrl,
324 bool has_ibi_size)
325 {
326 struct i3c_ccc_payload ccc_payload;
327 uint8_t data[3];
328
329 __ASSERT_NO_MSG(controller != NULL);
330
331 memset(&ccc_payload, 0, sizeof(ccc_payload));
332
333 ccc_payload.ccc.id = I3C_CCC_SETMRL(true);
334
335 ccc_payload.ccc.data = &data[0];
336 ccc_payload.ccc.data_len = has_ibi_size ? 3 : 2;
337
338 /* The actual length is MSB first. So order the data. */
339 sys_put_be16(mrl->len, data);
340
341 if (has_ibi_size) {
342 data[2] = mrl->ibi_len;
343 }
344
345 return i3c_do_ccc(controller, &ccc_payload);
346 }
347
i3c_ccc_do_setmrl(const struct i3c_device_desc * target,const struct i3c_ccc_mrl * mrl)348 int i3c_ccc_do_setmrl(const struct i3c_device_desc *target,
349 const struct i3c_ccc_mrl *mrl)
350 {
351 struct i3c_ccc_payload ccc_payload;
352 struct i3c_ccc_target_payload ccc_tgt_payload;
353 uint8_t data[3];
354
355 __ASSERT_NO_MSG(target != NULL);
356 __ASSERT_NO_MSG(target->bus != NULL);
357
358 memset(&ccc_payload, 0, sizeof(ccc_payload));
359
360 ccc_tgt_payload.addr = target->dynamic_addr;
361 ccc_tgt_payload.rnw = 0;
362 ccc_tgt_payload.data = &data[0];
363
364 ccc_payload.ccc.id = I3C_CCC_SETMRL(false);
365 ccc_payload.targets.payloads = &ccc_tgt_payload;
366 ccc_payload.targets.num_targets = 1;
367
368 /* The actual length is MSB first. So order the data. */
369 sys_put_be16(mrl->len, data);
370
371 if ((target->bcr & I3C_BCR_IBI_PAYLOAD_HAS_DATA_BYTE)
372 == I3C_BCR_IBI_PAYLOAD_HAS_DATA_BYTE) {
373 ccc_tgt_payload.data_len = 3;
374
375 data[2] = mrl->ibi_len;
376 } else {
377 ccc_tgt_payload.data_len = 2;
378 }
379
380 return i3c_do_ccc(target->bus, &ccc_payload);
381 }
382
i3c_ccc_do_getmrl(const struct i3c_device_desc * target,struct i3c_ccc_mrl * mrl)383 int i3c_ccc_do_getmrl(const struct i3c_device_desc *target,
384 struct i3c_ccc_mrl *mrl)
385 {
386 struct i3c_ccc_payload ccc_payload;
387 struct i3c_ccc_target_payload ccc_tgt_payload;
388 uint8_t data[3];
389 bool has_ibi_sz;
390 int ret;
391
392 __ASSERT_NO_MSG(target != NULL);
393 __ASSERT_NO_MSG(target->bus != NULL);
394 __ASSERT_NO_MSG(mrl != NULL);
395
396 has_ibi_sz = (target->bcr & I3C_BCR_IBI_PAYLOAD_HAS_DATA_BYTE)
397 == I3C_BCR_IBI_PAYLOAD_HAS_DATA_BYTE;
398
399 ccc_tgt_payload.addr = target->dynamic_addr;
400 ccc_tgt_payload.rnw = 1;
401 ccc_tgt_payload.data = &data[0];
402 ccc_tgt_payload.data_len = has_ibi_sz ? 3 : 2;
403
404 memset(&ccc_payload, 0, sizeof(ccc_payload));
405 ccc_payload.ccc.id = I3C_CCC_GETMRL;
406 ccc_payload.targets.payloads = &ccc_tgt_payload;
407 ccc_payload.targets.num_targets = 1;
408
409 ret = i3c_do_ccc(target->bus, &ccc_payload);
410
411 if (ret == 0) {
412 /* The actual length is MSB first. So order the data. */
413 mrl->len = sys_get_be16(data);
414
415 if (has_ibi_sz) {
416 mrl->ibi_len = data[2];
417 }
418 }
419
420 return ret;
421 }
422
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)423 int i3c_ccc_do_getstatus(const struct i3c_device_desc *target,
424 union i3c_ccc_getstatus *status,
425 enum i3c_ccc_getstatus_fmt fmt,
426 enum i3c_ccc_getstatus_defbyte defbyte)
427 {
428 struct i3c_ccc_payload ccc_payload;
429 struct i3c_ccc_target_payload ccc_tgt_payload;
430 uint8_t defining_byte;
431 uint8_t data[2];
432 int ret;
433
434 __ASSERT_NO_MSG(target != NULL);
435 __ASSERT_NO_MSG(target->bus != NULL);
436 __ASSERT_NO_MSG(status != NULL);
437
438 ccc_tgt_payload.addr = target->dynamic_addr;
439 ccc_tgt_payload.rnw = 1;
440 ccc_tgt_payload.data = &data[0];
441
442 if (fmt == GETSTATUS_FORMAT_1) {
443 ccc_tgt_payload.data_len = 2;
444 } else if (fmt == GETSTATUS_FORMAT_2) {
445 switch (defbyte) {
446 case GETSTATUS_FORMAT_2_TGTSTAT:
447 __fallthrough;
448 case GETSTATUS_FORMAT_2_PRECR:
449 ccc_tgt_payload.data_len = 2;
450 break;
451 default:
452 ret = -EINVAL;
453 goto out;
454 }
455 } else {
456 ret = -EINVAL;
457 goto out;
458 }
459
460 memset(&ccc_payload, 0, sizeof(ccc_payload));
461 ccc_payload.ccc.id = I3C_CCC_GETSTATUS;
462 ccc_payload.targets.payloads = &ccc_tgt_payload;
463 ccc_payload.targets.num_targets = 1;
464
465 if (fmt == GETSTATUS_FORMAT_2) {
466 defining_byte = (uint8_t)defbyte;
467
468 ccc_payload.ccc.data = &defining_byte;
469 ccc_payload.ccc.data_len = 1;
470 }
471
472 ret = i3c_do_ccc(target->bus, &ccc_payload);
473
474 if (ret == 0) {
475 /* Received data is MSB first. So order the data. */
476 if (fmt == GETSTATUS_FORMAT_1) {
477 status->fmt1.status = sys_get_be16(data);
478 } else if (fmt == GETSTATUS_FORMAT_2) {
479 switch (defbyte) {
480 case GETSTATUS_FORMAT_2_TGTSTAT:
481 __fallthrough;
482 case GETSTATUS_FORMAT_2_PRECR:
483 status->fmt2.raw_u16 = sys_get_be16(data);
484 break;
485 default:
486 break;
487 }
488 }
489 }
490
491 out:
492 return ret;
493 }
494
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)495 int i3c_ccc_do_getcaps(const struct i3c_device_desc *target,
496 union i3c_ccc_getcaps *caps,
497 enum i3c_ccc_getcaps_fmt fmt,
498 enum i3c_ccc_getcaps_defbyte defbyte)
499 {
500 struct i3c_ccc_payload ccc_payload;
501 struct i3c_ccc_target_payload ccc_tgt_payload;
502 uint8_t defining_byte;
503 uint8_t data[4];
504 uint8_t len;
505 int ret;
506
507 __ASSERT_NO_MSG(target != NULL);
508 __ASSERT_NO_MSG(target->bus != NULL);
509 __ASSERT_NO_MSG(caps != NULL);
510
511 ccc_tgt_payload.addr = target->dynamic_addr;
512 ccc_tgt_payload.rnw = 1;
513 ccc_tgt_payload.data = &data[0];
514
515 if (fmt == GETCAPS_FORMAT_1) {
516 /* Could be 1-4 Data Bytes Returned */
517 ccc_tgt_payload.data_len = 4;
518 } else if (fmt == GETCAPS_FORMAT_2) {
519 switch (defbyte) {
520 case GETCAPS_FORMAT_2_CRCAPS:
521 __fallthrough;
522 case GETCAPS_FORMAT_2_VTCAPS:
523 /* Could be 1-2 Data Bytes Returned*/
524 ccc_tgt_payload.data_len = 2;
525 break;
526 case GETCAPS_FORMAT_2_TGTCAPS:
527 __fallthrough;
528 case GETCAPS_FORMAT_2_TESTPAT:
529 /* Could be 1-4 Data Bytes Returned */
530 ccc_tgt_payload.data_len = 4;
531 break;
532 default:
533 ret = -EINVAL;
534 goto out;
535 }
536 } else {
537 ret = -EINVAL;
538 goto out;
539 }
540
541 memset(&ccc_payload, 0, sizeof(ccc_payload));
542 ccc_payload.ccc.id = I3C_CCC_GETCAPS;
543 ccc_payload.targets.payloads = &ccc_tgt_payload;
544 ccc_payload.targets.num_targets = 1;
545
546 if (fmt == GETCAPS_FORMAT_2) {
547 defining_byte = (uint8_t)defbyte;
548
549 ccc_payload.ccc.data = &defining_byte;
550 ccc_payload.ccc.data_len = 1;
551 }
552
553 ret = i3c_do_ccc(target->bus, &ccc_payload);
554
555 if (ret == 0) {
556 /* GETCAPS will return a variable length */
557 len = ccc_tgt_payload.num_xfer;
558
559 if (fmt == GETCAPS_FORMAT_1) {
560 memcpy(caps->fmt1.getcaps, data, len);
561 /* for values not received, assume default (1'b0) */
562 memset(&caps->fmt1.getcaps[len], 0, sizeof(caps->fmt1.getcaps) - len);
563 } else if (fmt == GETCAPS_FORMAT_2) {
564 switch (defbyte) {
565 case GETCAPS_FORMAT_2_CRCAPS:
566 memcpy(caps->fmt2.crcaps, data, len);
567 /* for values not received, assume default (1'b0) */
568 memset(&caps->fmt2.crcaps[len], 0, sizeof(caps->fmt2.crcaps) - len);
569 break;
570 case GETCAPS_FORMAT_2_VTCAPS:
571 memcpy(caps->fmt2.vtcaps, data, len);
572 /* for values not received, assume default (1'b0) */
573 memset(&caps->fmt2.vtcaps[len], 0, sizeof(caps->fmt2.vtcaps) - len);
574 break;
575 case GETCAPS_FORMAT_2_TGTCAPS:
576 memcpy(caps->fmt2.tgtcaps, data, len);
577 /* for values not received, assume default (1'b0) */
578 memset(&caps->fmt2.tgtcaps[len], 0,
579 sizeof(caps->fmt2.tgtcaps) - len);
580 break;
581 case GETCAPS_FORMAT_2_TESTPAT:
582 /* should always be 4 data bytes */
583 caps->fmt2.testpat = sys_get_be32(data);
584 break;
585 default:
586 break;
587 }
588 }
589 }
590
591 out:
592 return ret;
593 }
594