Lines Matching +full:ports +full:- +full:word +full:- +full:length

1 // SPDX-License-Identifier: GPL-2.0
3 * Thunderbolt driver - eeprom access
16 * tb_eeprom_ctl_write() - write control word
20 return tb_sw_write(sw, ctl, TB_CFG_SWITCH, sw->cap_plug_events + ROUTER_CS_4, 1); in tb_eeprom_ctl_write()
24 * tb_eeprom_ctl_write() - read control word
28 return tb_sw_read(sw, ctl, TB_CFG_SWITCH, sw->cap_plug_events + ROUTER_CS_4, 1); in tb_eeprom_ctl_read()
37 * tb_eeprom_active - enable rom access
66 * tb_eeprom_transfer - transfer one bit
68 * If TB_EEPROM_IN is passed, then the bit can be retrieved from ctl->fl_do.
69 * If TB_EEPROM_OUT is passed, then ctl->fl_di will be written.
80 ctl->fl_sk = 1; in tb_eeprom_transfer()
89 ctl->fl_sk = 0; in tb_eeprom_transfer()
94 * tb_eeprom_out - write one byte to the bus
114 * tb_eeprom_in - read one byte from the bus
135 * tb_eeprom_get_drom_offset - get drom offset within eeprom
142 if (!sw->cap_plug_events) { in tb_eeprom_get_drom_offset()
144 return -ENODEV; in tb_eeprom_get_drom_offset()
146 res = tb_sw_read(sw, &cap, TB_CFG_SWITCH, sw->cap_plug_events, in tb_eeprom_get_drom_offset()
153 return -ENODEV; in tb_eeprom_get_drom_offset()
159 return -ENXIO; in tb_eeprom_get_drom_offset()
166 * tb_eeprom_read_n - read count bytes from offset into val
224 /* BYTES 1-8 */
226 /* BYTES 9-12 */
232 /* BYTES 16-21 - Only for TBT DROM, nonexistent in USB4 DROM */
240 /* force unsigned to prevent "one-bit signed bitfield" warning */
258 /* BYTES 0-1 */
270 /* BYTES 4 - 5 TODO decode */
275 /* BYTES 6-7, TODO: verify (find hardware that has these set) */
295 * tb_drom_read_uid_only() - Read UID directly from DROM
299 * Does not use the cached copy in sw->drom. Used during resume to check switch
317 return -EIO; in tb_drom_read_uid_only()
330 switch (header->index) { in tb_drom_parse_entry_generic()
332 /* Length includes 2 bytes header so remove it before copy */ in tb_drom_parse_entry_generic()
333 sw->vendor_name = kstrndup(entry->data, in tb_drom_parse_entry_generic()
334 header->len - sizeof(*header), GFP_KERNEL); in tb_drom_parse_entry_generic()
335 if (!sw->vendor_name) in tb_drom_parse_entry_generic()
336 return -ENOMEM; in tb_drom_parse_entry_generic()
340 sw->device_name = kstrndup(entry->data, in tb_drom_parse_entry_generic()
341 header->len - sizeof(*header), GFP_KERNEL); in tb_drom_parse_entry_generic()
342 if (!sw->device_name) in tb_drom_parse_entry_generic()
343 return -ENOMEM; in tb_drom_parse_entry_generic()
349 if (!sw->vendor && !sw->device) { in tb_drom_parse_entry_generic()
350 sw->vendor = desc->idVendor; in tb_drom_parse_entry_generic()
351 sw->device = desc->idProduct; in tb_drom_parse_entry_generic()
368 * Some DROMs list more ports than the controller actually has in tb_drom_parse_entry_port()
371 if (header->index > sw->config.max_port_number) { in tb_drom_parse_entry_port()
372 dev_info_once(&sw->dev, "ignoring unnecessary extra entries in DROM\n"); in tb_drom_parse_entry_port()
376 port = &sw->ports[header->index]; in tb_drom_parse_entry_port()
377 port->disabled = header->port_disabled; in tb_drom_parse_entry_port()
378 if (port->disabled) in tb_drom_parse_entry_port()
388 if (header->len != sizeof(*entry)) { in tb_drom_parse_entry_port()
391 header->len, sizeof(struct tb_drom_entry_port)); in tb_drom_parse_entry_port()
392 return -EIO; in tb_drom_parse_entry_port()
394 port->link_nr = entry->link_nr; in tb_drom_parse_entry_port()
395 if (entry->has_dual_link_port) in tb_drom_parse_entry_port()
396 port->dual_link_port = in tb_drom_parse_entry_port()
397 &port->sw->ports[entry->dual_link_port_nr]; in tb_drom_parse_entry_port()
403 * tb_drom_parse_entries - parse the linked list of drom entries
405 * Drom must have been copied to sw->drom.
409 struct tb_drom_header *header = (void *) sw->drom; in tb_drom_parse_entries()
411 u16 drom_size = header->data_len + TB_DROM_DATA_START; in tb_drom_parse_entries()
415 struct tb_drom_entry_header *entry = (void *) (sw->drom + pos); in tb_drom_parse_entries()
416 if (pos + 1 == drom_size || pos + entry->len > drom_size in tb_drom_parse_entries()
417 || !entry->len) { in tb_drom_parse_entries()
419 return -EIO; in tb_drom_parse_entries()
422 switch (entry->type) { in tb_drom_parse_entries()
433 pos += entry->len; in tb_drom_parse_entries()
439 * tb_drom_copy_efi - copy drom supplied by EFI to sw->drom if present
443 struct device *dev = &sw->tb->nhi->pdev->dev; in tb_drom_copy_efi()
448 return -EINVAL; in tb_drom_copy_efi()
450 sw->drom = kmalloc(len, GFP_KERNEL); in tb_drom_copy_efi()
451 if (!sw->drom) in tb_drom_copy_efi()
452 return -ENOMEM; in tb_drom_copy_efi()
454 res = device_property_read_u8_array(dev, "ThunderboltDROM", sw->drom, in tb_drom_copy_efi()
459 *size = ((struct tb_drom_header *)sw->drom)->data_len + in tb_drom_copy_efi()
467 kfree(sw->drom); in tb_drom_copy_efi()
468 sw->drom = NULL; in tb_drom_copy_efi()
469 return -EINVAL; in tb_drom_copy_efi()
477 if (!sw->dma_port) in tb_drom_copy_nvm()
478 return -ENODEV; in tb_drom_copy_nvm()
485 return -ENODEV; in tb_drom_copy_nvm()
487 ret = dma_port_flash_read(sw->dma_port, drom_offset + 14, size, in tb_drom_copy_nvm()
494 sw->drom = kzalloc(*size, GFP_KERNEL); in tb_drom_copy_nvm()
495 if (!sw->drom) in tb_drom_copy_nvm()
496 return -ENOMEM; in tb_drom_copy_nvm()
498 ret = dma_port_flash_read(sw->dma_port, drom_offset, sw->drom, *size); in tb_drom_copy_nvm()
506 tb_drom_read_uid_only(sw, &sw->uid); in tb_drom_copy_nvm()
510 kfree(sw->drom); in tb_drom_copy_nvm()
511 sw->drom = NULL; in tb_drom_copy_nvm()
525 sw->drom = kzalloc(*size, GFP_KERNEL); in usb4_copy_drom()
526 if (!sw->drom) in usb4_copy_drom()
527 return -ENOMEM; in usb4_copy_drom()
529 ret = usb4_switch_drom_read(sw, 0, sw->drom, *size); in usb4_copy_drom()
531 kfree(sw->drom); in usb4_copy_drom()
532 sw->drom = NULL; in usb4_copy_drom()
549 tb_sw_dbg(sw, "reading DROM (length: %#x)\n", *size); in tb_drom_bit_bang()
552 return -EIO; in tb_drom_bit_bang()
555 sw->drom = kzalloc(*size, GFP_KERNEL); in tb_drom_bit_bang()
556 if (!sw->drom) in tb_drom_bit_bang()
557 return -ENOMEM; in tb_drom_bit_bang()
559 ret = tb_eeprom_read_n(sw, 0, sw->drom, *size); in tb_drom_bit_bang()
566 kfree(sw->drom); in tb_drom_bit_bang()
567 sw->drom = NULL; in tb_drom_bit_bang()
574 (const struct tb_drom_header *)sw->drom; in tb_drom_parse_v1()
577 crc = tb_crc8((u8 *) &header->uid, 8); in tb_drom_parse_v1()
578 if (crc != header->uid_crc8) { in tb_drom_parse_v1()
581 header->uid_crc8, crc); in tb_drom_parse_v1()
582 return -EIO; in tb_drom_parse_v1()
584 if (!sw->uid) in tb_drom_parse_v1()
585 sw->uid = header->uid; in tb_drom_parse_v1()
586 sw->vendor = header->vendor_id; in tb_drom_parse_v1()
587 sw->device = header->model_id; in tb_drom_parse_v1()
589 crc = tb_crc32(sw->drom + TB_DROM_DATA_START, header->data_len); in tb_drom_parse_v1()
590 if (crc != header->data_crc32) { in tb_drom_parse_v1()
593 header->data_crc32, crc); in tb_drom_parse_v1()
602 (const struct tb_drom_header *)sw->drom; in usb4_drom_parse()
605 crc = tb_crc32(sw->drom + TB_DROM_DATA_START, header->data_len); in usb4_drom_parse()
606 if (crc != header->data_crc32) { in usb4_drom_parse()
609 header->data_crc32, crc); in usb4_drom_parse()
617 const struct tb_drom_header *header = (const void *)sw->drom; in tb_drom_parse()
620 if (header->data_len + TB_DROM_DATA_START != size) { in tb_drom_parse()
622 ret = -EIO; in tb_drom_parse()
626 tb_sw_dbg(sw, "DROM version: %d\n", header->device_rom_revision); in tb_drom_parse()
628 switch (header->device_rom_revision) { in tb_drom_parse()
634 header->device_rom_revision); in tb_drom_parse()
649 kfree(sw->drom); in tb_drom_parse()
650 sw->drom = NULL; in tb_drom_parse()
660 usb4_switch_read_uid(sw, &sw->uid); in tb_drom_host_read()
670 tb_drom_read_uid_only(sw, &sw->uid); in tb_drom_host_read()
682 usb4_switch_read_uid(sw, &sw->uid); in tb_drom_device_read()
695 * tb_drom_read() - Copy DROM to sw->drom and parse it
706 if (sw->drom) in tb_drom_read()