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
302 int tb_drom_read_uid_only(struct tb_switch *sw, u64 *uid) in tb_drom_read_uid_only() argument
309 res = tb_eeprom_read_n(sw, 0, data, 9); in tb_drom_read_uid_only()
315 tb_sw_warn(sw, "uid crc8 mismatch (expected: %#x, got: %#x)\n", in tb_drom_read_uid_only()
324 static int tb_drom_parse_entry_generic(struct tb_switch *sw, in tb_drom_parse_entry_generic() argument
333 sw->vendor_name = kstrndup(entry->data, in tb_drom_parse_entry_generic()
335 if (!sw->vendor_name) in tb_drom_parse_entry_generic()
340 sw->device_name = kstrndup(entry->data, in tb_drom_parse_entry_generic()
342 if (!sw->device_name) 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()
360 static int tb_drom_parse_entry_port(struct tb_switch *sw, in tb_drom_parse_entry_port() argument
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()
389 tb_sw_warn(sw, in tb_drom_parse_entry_port()
397 &port->sw->ports[entry->dual_link_port_nr]; in tb_drom_parse_entry_port()
405 * Drom must have been copied to sw->drom.
407 static int tb_drom_parse_entries(struct tb_switch *sw, size_t header_size) in tb_drom_parse_entries() argument
409 struct tb_drom_header *header = (void *) sw->drom; in tb_drom_parse_entries()
415 struct tb_drom_entry_header *entry = (void *) (sw->drom + pos); in tb_drom_parse_entries()
418 tb_sw_warn(sw, "DROM buffer overrun\n"); in tb_drom_parse_entries()
424 res = tb_drom_parse_entry_generic(sw, entry); in tb_drom_parse_entries()
427 res = tb_drom_parse_entry_port(sw, entry); in tb_drom_parse_entries()
438 static int tb_switch_drom_alloc(struct tb_switch *sw, size_t size) in tb_switch_drom_alloc() argument
440 sw->drom = kzalloc(size, GFP_KERNEL); in tb_switch_drom_alloc()
441 if (!sw->drom) 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()
451 static void tb_switch_drom_free(struct tb_switch *sw) in tb_switch_drom_free() argument
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
464 static int tb_drom_copy_efi(struct tb_switch *sw, u16 *size) in tb_drom_copy_efi() argument
466 struct device *dev = &sw->tb->nhi->pdev->dev; in tb_drom_copy_efi()
473 res = tb_switch_drom_alloc(sw, len); 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()
490 tb_switch_drom_free(sw); in tb_drom_copy_efi()
494 static int tb_drom_copy_nvm(struct tb_switch *sw, u16 *size) in tb_drom_copy_nvm() argument
499 if (!sw->dma_port) in tb_drom_copy_nvm()
502 ret = tb_eeprom_get_drom_offset(sw, &drom_offset); in tb_drom_copy_nvm()
509 ret = dma_port_flash_read(sw->dma_port, drom_offset + 14, size, in tb_drom_copy_nvm()
516 ret = tb_switch_drom_alloc(sw, *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()
522 tb_switch_drom_free(sw); in tb_drom_copy_nvm()
530 tb_drom_read_uid_only(sw, &sw->uid); in tb_drom_copy_nvm()
534 static int usb4_copy_drom(struct tb_switch *sw, u16 *size) in usb4_copy_drom() argument
538 ret = usb4_switch_drom_read(sw, 14, size, sizeof(*size)); in usb4_copy_drom()
544 ret = tb_switch_drom_alloc(sw, *size); in usb4_copy_drom()
548 ret = usb4_switch_drom_read(sw, 0, sw->drom, *size); in usb4_copy_drom()
550 tb_switch_drom_free(sw); in usb4_copy_drom()
555 static int tb_drom_bit_bang(struct tb_switch *sw, u16 *size) in tb_drom_bit_bang() argument
559 ret = tb_eeprom_read_n(sw, 14, (u8 *)size, 2); in tb_drom_bit_bang()
566 tb_sw_dbg(sw, "reading DROM (length: %#x)\n", *size); in tb_drom_bit_bang()
568 tb_sw_warn(sw, "DROM too small, aborting\n"); in tb_drom_bit_bang()
572 ret = tb_switch_drom_alloc(sw, *size); in tb_drom_bit_bang()
576 ret = tb_eeprom_read_n(sw, 0, sw->drom, *size); in tb_drom_bit_bang()
578 tb_switch_drom_free(sw); in tb_drom_bit_bang()
583 static int tb_drom_parse_v1(struct tb_switch *sw) in tb_drom_parse_v1() argument
586 (const struct tb_drom_header *)sw->drom; in tb_drom_parse_v1()
591 tb_sw_warn(sw, 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()
603 tb_sw_warn(sw, in tb_drom_parse_v1()
608 return tb_drom_parse_entries(sw, TB_DROM_HEADER_SIZE); in tb_drom_parse_v1()
611 static int usb4_drom_parse(struct tb_switch *sw) in usb4_drom_parse() argument
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()
619 tb_sw_warn(sw, in usb4_drom_parse()
624 return tb_drom_parse_entries(sw, USB4_DROM_HEADER_SIZE); in usb4_drom_parse()
627 static int tb_drom_parse(struct tb_switch *sw, u16 size) in tb_drom_parse() argument
629 const struct tb_drom_header *header = (const void *)sw->drom; in tb_drom_parse()
633 tb_sw_warn(sw, "DROM size mismatch\n"); in tb_drom_parse()
638 tb_sw_dbg(sw, "DROM version: %d\n", header->device_rom_revision); in tb_drom_parse()
642 ret = usb4_drom_parse(sw); in tb_drom_parse()
645 tb_sw_warn(sw, "DROM device_rom_revision %#x unknown\n", in tb_drom_parse()
649 ret = tb_drom_parse_v1(sw); in tb_drom_parse()
654 tb_sw_warn(sw, "parsing DROM failed\n"); in tb_drom_parse()
661 tb_switch_drom_free(sw); in tb_drom_parse()
665 static int tb_drom_host_read(struct tb_switch *sw) in tb_drom_host_read() argument
669 if (tb_switch_is_usb4(sw)) { in tb_drom_host_read()
670 usb4_switch_read_uid(sw, &sw->uid); in tb_drom_host_read()
671 if (!usb4_copy_drom(sw, &size)) in tb_drom_host_read()
672 return tb_drom_parse(sw, size); in tb_drom_host_read()
674 if (!tb_drom_copy_efi(sw, &size)) in tb_drom_host_read()
675 return tb_drom_parse(sw, size); in tb_drom_host_read()
677 if (!tb_drom_copy_nvm(sw, &size)) in tb_drom_host_read()
678 return tb_drom_parse(sw, size); in tb_drom_host_read()
680 tb_drom_read_uid_only(sw, &sw->uid); in tb_drom_host_read()
686 static int tb_drom_device_read(struct tb_switch *sw) in tb_drom_device_read() argument
691 if (tb_switch_is_usb4(sw)) { in tb_drom_device_read()
692 usb4_switch_read_uid(sw, &sw->uid); in tb_drom_device_read()
693 ret = usb4_copy_drom(sw, &size); in tb_drom_device_read()
695 ret = tb_drom_bit_bang(sw, &size); in tb_drom_device_read()
701 return tb_drom_parse(sw, size); in tb_drom_device_read()
705 * tb_drom_read() - Copy DROM to sw->drom and parse it
706 * @sw: Router whose DROM to read and parse
709 * populates the fields in @sw accordingly. Can be called for any router
714 int tb_drom_read(struct tb_switch *sw) in tb_drom_read() argument
716 if (sw->drom) in tb_drom_read()
719 if (!tb_route(sw)) in tb_drom_read()
720 return tb_drom_host_read(sw); in tb_drom_read()
721 return tb_drom_device_read(sw); in tb_drom_read()