Lines Matching full:sw

18 static int tb_eeprom_ctl_write(struct tb_switch *sw, struct tb_eeprom_ctl *ctl)  in tb_eeprom_ctl_write()  argument
20 return tb_sw_write(sw, ctl, TB_CFG_SWITCH, sw->cap_plug_events + ROUTER_CS_4, 1); in tb_eeprom_ctl_write()
26 static int tb_eeprom_ctl_read(struct tb_switch *sw, struct tb_eeprom_ctl *ctl) in tb_eeprom_ctl_read() argument
28 return tb_sw_read(sw, ctl, TB_CFG_SWITCH, sw->cap_plug_events + ROUTER_CS_4, 1); in tb_eeprom_ctl_read()
42 static int tb_eeprom_active(struct tb_switch *sw, bool enable) in tb_eeprom_active() argument
45 int res = tb_eeprom_ctl_read(sw, &ctl); in tb_eeprom_active()
50 res = tb_eeprom_ctl_write(sw, &ctl); in tb_eeprom_active()
54 return tb_eeprom_ctl_write(sw, &ctl); in tb_eeprom_active()
57 res = tb_eeprom_ctl_write(sw, &ctl); in tb_eeprom_active()
61 return tb_eeprom_ctl_write(sw, &ctl); in tb_eeprom_active()
71 static int tb_eeprom_transfer(struct tb_switch *sw, struct tb_eeprom_ctl *ctl, in tb_eeprom_transfer() argument
76 res = tb_eeprom_ctl_write(sw, ctl); in tb_eeprom_transfer()
81 res = tb_eeprom_ctl_write(sw, ctl); in tb_eeprom_transfer()
85 res = tb_eeprom_ctl_read(sw, ctl); in tb_eeprom_transfer()
90 return tb_eeprom_ctl_write(sw, ctl); in tb_eeprom_transfer()
96 static int tb_eeprom_out(struct tb_switch *sw, u8 val) in tb_eeprom_out() argument
100 int res = tb_eeprom_ctl_read(sw, &ctl); in tb_eeprom_out()
105 res = tb_eeprom_transfer(sw, &ctl, TB_EEPROM_OUT); in tb_eeprom_out()
116 static int tb_eeprom_in(struct tb_switch *sw, u8 *val) in tb_eeprom_in() argument
120 int res = tb_eeprom_ctl_read(sw, &ctl); in tb_eeprom_in()
126 res = tb_eeprom_transfer(sw, &ctl, TB_EEPROM_IN); in tb_eeprom_in()
137 static int tb_eeprom_get_drom_offset(struct tb_switch *sw, u16 *offset) in tb_eeprom_get_drom_offset() argument
142 if (!sw->cap_plug_events) { in tb_eeprom_get_drom_offset()
143 tb_sw_warn(sw, "no TB_CAP_PLUG_EVENTS, cannot read eeprom\n"); 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()
152 tb_sw_warn(sw, "no NVM\n"); in tb_eeprom_get_drom_offset()
157 tb_sw_warn(sw, "drom offset is larger than 0xffff: %#x\n", in tb_eeprom_get_drom_offset()
168 static int tb_eeprom_read_n(struct tb_switch *sw, u16 offset, u8 *val, in tb_eeprom_read_n() argument
174 res = tb_eeprom_get_drom_offset(sw, &drom_offset); in tb_eeprom_read_n()
180 res = tb_eeprom_active(sw, true); in tb_eeprom_read_n()
183 res = tb_eeprom_out(sw, 3); in tb_eeprom_read_n()
186 res = tb_eeprom_out(sw, offset >> 8); in tb_eeprom_read_n()
189 res = tb_eeprom_out(sw, offset); in tb_eeprom_read_n()
193 res = tb_eeprom_in(sw, val + i); in tb_eeprom_read_n()
197 return tb_eeprom_active(sw, false); in tb_eeprom_read_n()
296 * @sw: Router whose UID to read
299 * Does not use the cached copy in sw->drom. Used during resume to check switch
304 int tb_drom_read_uid_only(struct tb_switch *sw, u64 *uid) in tb_drom_read_uid_only() argument
311 res = tb_eeprom_read_n(sw, 0, data, 9); in tb_drom_read_uid_only()
317 tb_sw_warn(sw, "uid crc8 mismatch (expected: %#x, got: %#x)\n", in tb_drom_read_uid_only()
326 static int tb_drom_parse_entry_generic(struct tb_switch *sw, in tb_drom_parse_entry_generic() argument
335 sw->vendor_name = kstrndup(entry->data, in tb_drom_parse_entry_generic()
337 if (!sw->vendor_name) in tb_drom_parse_entry_generic()
342 sw->device_name = kstrndup(entry->data, in tb_drom_parse_entry_generic()
344 if (!sw->device_name) in tb_drom_parse_entry_generic()
351 if (!sw->vendor && !sw->device) { in tb_drom_parse_entry_generic()
352 sw->vendor = desc->idVendor; in tb_drom_parse_entry_generic()
353 sw->device = desc->idProduct; in tb_drom_parse_entry_generic()
362 static int tb_drom_parse_entry_port(struct tb_switch *sw, in tb_drom_parse_entry_port() argument
373 if (header->index > sw->config.max_port_number) { in tb_drom_parse_entry_port()
374 dev_info_once(&sw->dev, "ignoring unnecessary extra entries in DROM\n"); in tb_drom_parse_entry_port()
378 port = &sw->ports[header->index]; in tb_drom_parse_entry_port()
391 tb_sw_warn(sw, in tb_drom_parse_entry_port()
399 &port->sw->ports[entry->dual_link_port_nr]; in tb_drom_parse_entry_port()
407 * Drom must have been copied to sw->drom.
409 static int tb_drom_parse_entries(struct tb_switch *sw, size_t header_size) in tb_drom_parse_entries() argument
411 struct tb_drom_header *header = (void *) sw->drom; in tb_drom_parse_entries()
417 struct tb_drom_entry_header *entry = (void *) (sw->drom + pos); in tb_drom_parse_entries()
420 tb_sw_warn(sw, "DROM buffer overrun\n"); in tb_drom_parse_entries()
426 res = tb_drom_parse_entry_generic(sw, entry); in tb_drom_parse_entries()
429 res = tb_drom_parse_entry_port(sw, entry); in tb_drom_parse_entries()
440 static int tb_switch_drom_alloc(struct tb_switch *sw, size_t size) in tb_switch_drom_alloc() argument
442 sw->drom = kzalloc(size, GFP_KERNEL); in tb_switch_drom_alloc()
443 if (!sw->drom) in tb_switch_drom_alloc()
447 sw->drom_blob.data = sw->drom; in tb_switch_drom_alloc()
448 sw->drom_blob.size = size; in tb_switch_drom_alloc()
453 static void tb_switch_drom_free(struct tb_switch *sw) in tb_switch_drom_free() argument
456 sw->drom_blob.data = NULL; in tb_switch_drom_free()
457 sw->drom_blob.size = 0; in tb_switch_drom_free()
459 kfree(sw->drom); in tb_switch_drom_free()
460 sw->drom = NULL; in tb_switch_drom_free()
464 * tb_drom_copy_efi - copy drom supplied by EFI to sw->drom if present
466 static int tb_drom_copy_efi(struct tb_switch *sw, u16 *size) in tb_drom_copy_efi() argument
468 struct device *dev = &sw->tb->nhi->pdev->dev; in tb_drom_copy_efi()
475 res = tb_switch_drom_alloc(sw, len); in tb_drom_copy_efi()
479 res = device_property_read_u8_array(dev, "ThunderboltDROM", sw->drom, in tb_drom_copy_efi()
484 *size = ((struct tb_drom_header *)sw->drom)->data_len + in tb_drom_copy_efi()
492 tb_switch_drom_free(sw); in tb_drom_copy_efi()
496 static int tb_drom_copy_nvm(struct tb_switch *sw, u16 *size) in tb_drom_copy_nvm() argument
501 if (!sw->dma_port) in tb_drom_copy_nvm()
504 ret = tb_eeprom_get_drom_offset(sw, &drom_offset); in tb_drom_copy_nvm()
511 ret = dma_port_flash_read(sw->dma_port, drom_offset + 14, size, in tb_drom_copy_nvm()
518 ret = tb_switch_drom_alloc(sw, *size); in tb_drom_copy_nvm()
522 ret = dma_port_flash_read(sw->dma_port, drom_offset, sw->drom, *size); in tb_drom_copy_nvm()
524 tb_switch_drom_free(sw); in tb_drom_copy_nvm()
532 tb_drom_read_uid_only(sw, &sw->uid); in tb_drom_copy_nvm()
536 static int usb4_copy_drom(struct tb_switch *sw, u16 *size) in usb4_copy_drom() argument
540 ret = usb4_switch_drom_read(sw, 14, size, sizeof(*size)); in usb4_copy_drom()
546 ret = tb_switch_drom_alloc(sw, *size); in usb4_copy_drom()
550 ret = usb4_switch_drom_read(sw, 0, sw->drom, *size); in usb4_copy_drom()
552 tb_switch_drom_free(sw); in usb4_copy_drom()
557 static int tb_drom_bit_bang(struct tb_switch *sw, u16 *size) in tb_drom_bit_bang() argument
561 ret = tb_eeprom_read_n(sw, 14, (u8 *)size, 2); in tb_drom_bit_bang()
568 tb_sw_dbg(sw, "reading DROM (length: %#x)\n", *size); in tb_drom_bit_bang()
570 tb_sw_warn(sw, "DROM too small, aborting\n"); in tb_drom_bit_bang()
574 ret = tb_switch_drom_alloc(sw, *size); in tb_drom_bit_bang()
578 ret = tb_eeprom_read_n(sw, 0, sw->drom, *size); in tb_drom_bit_bang()
580 tb_switch_drom_free(sw); in tb_drom_bit_bang()
585 static int tb_drom_parse_v1(struct tb_switch *sw) in tb_drom_parse_v1() argument
588 (const struct tb_drom_header *)sw->drom; in tb_drom_parse_v1()
593 tb_sw_warn(sw, in tb_drom_parse_v1()
598 if (!sw->uid) in tb_drom_parse_v1()
599 sw->uid = header->uid; in tb_drom_parse_v1()
600 sw->vendor = header->vendor_id; in tb_drom_parse_v1()
601 sw->device = header->model_id; in tb_drom_parse_v1()
603 crc = tb_crc32(sw->drom + TB_DROM_DATA_START, header->data_len); in tb_drom_parse_v1()
605 tb_sw_warn(sw, in tb_drom_parse_v1()
610 return tb_drom_parse_entries(sw, TB_DROM_HEADER_SIZE); in tb_drom_parse_v1()
613 static int usb4_drom_parse(struct tb_switch *sw) in usb4_drom_parse() argument
616 (const struct tb_drom_header *)sw->drom; in usb4_drom_parse()
619 crc = tb_crc32(sw->drom + TB_DROM_DATA_START, header->data_len); in usb4_drom_parse()
621 tb_sw_warn(sw, in usb4_drom_parse()
626 return tb_drom_parse_entries(sw, USB4_DROM_HEADER_SIZE); in usb4_drom_parse()
629 static int tb_drom_parse(struct tb_switch *sw, u16 size) in tb_drom_parse() argument
631 const struct tb_drom_header *header = (const void *)sw->drom; in tb_drom_parse()
635 tb_sw_warn(sw, "DROM size mismatch\n"); in tb_drom_parse()
640 tb_sw_dbg(sw, "DROM version: %d\n", header->device_rom_revision); in tb_drom_parse()
644 ret = usb4_drom_parse(sw); in tb_drom_parse()
647 tb_sw_warn(sw, "DROM device_rom_revision %#x unknown\n", in tb_drom_parse()
651 ret = tb_drom_parse_v1(sw); in tb_drom_parse()
656 tb_sw_warn(sw, "parsing DROM failed\n"); in tb_drom_parse()
663 tb_switch_drom_free(sw); in tb_drom_parse()
667 static int tb_drom_host_read(struct tb_switch *sw) in tb_drom_host_read() argument
671 if (tb_switch_is_usb4(sw)) { in tb_drom_host_read()
672 usb4_switch_read_uid(sw, &sw->uid); in tb_drom_host_read()
673 if (!usb4_copy_drom(sw, &size)) in tb_drom_host_read()
674 return tb_drom_parse(sw, size); in tb_drom_host_read()
676 if (!tb_drom_copy_efi(sw, &size)) in tb_drom_host_read()
677 return tb_drom_parse(sw, size); in tb_drom_host_read()
679 if (!tb_drom_copy_nvm(sw, &size)) in tb_drom_host_read()
680 return tb_drom_parse(sw, size); in tb_drom_host_read()
682 tb_drom_read_uid_only(sw, &sw->uid); in tb_drom_host_read()
688 static int tb_drom_device_read(struct tb_switch *sw) in tb_drom_device_read() argument
693 if (tb_switch_is_usb4(sw)) { in tb_drom_device_read()
694 usb4_switch_read_uid(sw, &sw->uid); in tb_drom_device_read()
695 ret = usb4_copy_drom(sw, &size); in tb_drom_device_read()
697 ret = tb_drom_bit_bang(sw, &size); in tb_drom_device_read()
703 return tb_drom_parse(sw, size); in tb_drom_device_read()
707 * tb_drom_read() - Copy DROM to sw->drom and parse it
708 * @sw: Router whose DROM to read and parse
711 * populates the fields in @sw accordingly. Can be called for any router
716 int tb_drom_read(struct tb_switch *sw) in tb_drom_read() argument
718 if (sw->drom) in tb_drom_read()
721 if (!tb_route(sw)) in tb_drom_read()
722 return tb_drom_host_read(sw); in tb_drom_read()
723 return tb_drom_device_read(sw); in tb_drom_read()