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()
440 sw->drom = kzalloc(size, GFP_KERNEL); in tb_switch_drom_alloc()
441 if (!sw->drom) in tb_switch_drom_alloc()
442 return -ENOMEM; in tb_switch_drom_alloc()
445 sw->drom_blob.data = sw->drom; in tb_switch_drom_alloc()
446 sw->drom_blob.size = size; in tb_switch_drom_alloc()
454 sw->drom_blob.data = NULL; in tb_switch_drom_free()
455 sw->drom_blob.size = 0; in tb_switch_drom_free()
457 kfree(sw->drom); in tb_switch_drom_free()
458 sw->drom = NULL; in tb_switch_drom_free()
462 * tb_drom_copy_efi - copy drom supplied by EFI to sw->drom if present
466 struct device *dev = &sw->tb->nhi->pdev->dev; in tb_drom_copy_efi()
471 return -EINVAL; in tb_drom_copy_efi()
477 res = device_property_read_u8_array(dev, "ThunderboltDROM", sw->drom, in tb_drom_copy_efi()
482 *size = ((struct tb_drom_header *)sw->drom)->data_len + in tb_drom_copy_efi()
491 return -EINVAL; in tb_drom_copy_efi()
499 if (!sw->dma_port) in tb_drom_copy_nvm()
500 return -ENODEV; in tb_drom_copy_nvm()
507 return -ENODEV; in tb_drom_copy_nvm()
509 ret = dma_port_flash_read(sw->dma_port, drom_offset + 14, size, in tb_drom_copy_nvm()
520 ret = dma_port_flash_read(sw->dma_port, drom_offset, sw->drom, *size); in tb_drom_copy_nvm()
530 tb_drom_read_uid_only(sw, &sw->uid); in tb_drom_copy_nvm()
548 ret = usb4_switch_drom_read(sw, 0, sw->drom, *size); in usb4_copy_drom()
566 tb_sw_dbg(sw, "reading DROM (length: %#x)\n", *size); in tb_drom_bit_bang()
569 return -EIO; in tb_drom_bit_bang()
576 ret = tb_eeprom_read_n(sw, 0, sw->drom, *size); in tb_drom_bit_bang()
586 (const struct tb_drom_header *)sw->drom; in tb_drom_parse_v1()
589 crc = tb_crc8((u8 *) &header->uid, 8); in tb_drom_parse_v1()
590 if (crc != header->uid_crc8) { in tb_drom_parse_v1()
593 header->uid_crc8, crc); in tb_drom_parse_v1()
594 return -EIO; in tb_drom_parse_v1()
596 if (!sw->uid) in tb_drom_parse_v1()
597 sw->uid = header->uid; in tb_drom_parse_v1()
598 sw->vendor = header->vendor_id; in tb_drom_parse_v1()
599 sw->device = header->model_id; in tb_drom_parse_v1()
601 crc = tb_crc32(sw->drom + TB_DROM_DATA_START, header->data_len); in tb_drom_parse_v1()
602 if (crc != header->data_crc32) { in tb_drom_parse_v1()
605 header->data_crc32, crc); in tb_drom_parse_v1()
614 (const struct tb_drom_header *)sw->drom; in usb4_drom_parse()
617 crc = tb_crc32(sw->drom + TB_DROM_DATA_START, header->data_len); in usb4_drom_parse()
618 if (crc != header->data_crc32) { in usb4_drom_parse()
621 header->data_crc32, crc); in usb4_drom_parse()
629 const struct tb_drom_header *header = (const void *)sw->drom; in tb_drom_parse()
632 if (header->data_len + TB_DROM_DATA_START != size) { in tb_drom_parse()
634 ret = -EIO; in tb_drom_parse()
638 tb_sw_dbg(sw, "DROM version: %d\n", header->device_rom_revision); in tb_drom_parse()
640 switch (header->device_rom_revision) { in tb_drom_parse()
646 header->device_rom_revision); in tb_drom_parse()
670 usb4_switch_read_uid(sw, &sw->uid); in tb_drom_host_read()
680 tb_drom_read_uid_only(sw, &sw->uid); in tb_drom_host_read()
692 usb4_switch_read_uid(sw, &sw->uid); in tb_drom_device_read()
705 * tb_drom_read() - Copy DROM to sw->drom and parse it
716 if (sw->drom) in tb_drom_read()