Skip to content

Commit

Permalink
thunderbolt: Add initial support for USB4
Browse files Browse the repository at this point in the history
USB4 is the public specification based on Thunderbolt 3 protocol. There
are some differences in register layouts and flows. In addition to PCIe
and DP tunneling, USB4 supports tunneling of USB 3.x. USB4 is also
backward compatible with Thunderbolt 3 (and older generations but the
spec only talks about 3rd generation). USB4 compliant devices can be
identified by checking USB4 version field in router configuration space.

This patch adds initial support for USB4 compliant hosts and devices
which enables following features provided by the existing functionality
in the driver:

  - PCIe tunneling
  - Display Port tunneling
  - Host and device NVM firmware upgrade
  - P2P networking

This brings the USB4 support to the same level that we already have for
Thunderbolt 1, 2 and 3 devices.

Note the spec talks about host and device "routers" but in the driver we
still use term "switch" in most places. Both can be used interchangeably.

Co-developed-by: Rajmohan Mani <rajmohan.mani@intel.com>
Signed-off-by: Rajmohan Mani <rajmohan.mani@intel.com>
Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
Link: https://lore.kernel.org/r/20191217123345.31850-5-mika.westerberg@linux.intel.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
  • Loading branch information
Mika Westerberg authored and Greg Kroah-Hartman committed Dec 18, 2019
1 parent 210e9f5 commit b040798
Show file tree
Hide file tree
Showing 11 changed files with 1,158 additions and 117 deletions.
2 changes: 1 addition & 1 deletion drivers/thunderbolt/Makefile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# SPDX-License-Identifier: GPL-2.0-only
obj-${CONFIG_THUNDERBOLT} := thunderbolt.o
thunderbolt-objs := nhi.o nhi_ops.o ctl.o tb.o switch.o cap.o path.o tunnel.o eeprom.o
thunderbolt-objs += domain.o dma_port.o icm.o property.o xdomain.o lc.o
thunderbolt-objs += domain.o dma_port.o icm.o property.o xdomain.o lc.o usb4.o
53 changes: 48 additions & 5 deletions drivers/thunderbolt/eeprom.c
Original file line number Diff line number Diff line change
Expand Up @@ -487,6 +487,37 @@ static int tb_drom_copy_nvm(struct tb_switch *sw, u16 *size)
return ret;
}

static int usb4_copy_host_drom(struct tb_switch *sw, u16 *size)
{
int ret;

ret = usb4_switch_drom_read(sw, 14, size, sizeof(*size));
if (ret)
return ret;

/* Size includes CRC8 + UID + CRC32 */
*size += 1 + 8 + 4;
sw->drom = kzalloc(*size, GFP_KERNEL);
if (!sw->drom)
return -ENOMEM;

ret = usb4_switch_drom_read(sw, 0, sw->drom, *size);
if (ret) {
kfree(sw->drom);
sw->drom = NULL;
}

return ret;
}

static int tb_drom_read_n(struct tb_switch *sw, u16 offset, u8 *val,
size_t count)
{
if (tb_switch_is_usb4(sw))
return usb4_switch_drom_read(sw, offset, val, count);
return tb_eeprom_read_n(sw, offset, val, count);
}

/**
* tb_drom_read - copy drom to sw->drom and parse it
*/
Expand All @@ -512,14 +543,26 @@ int tb_drom_read(struct tb_switch *sw)
goto parse;

/*
* The root switch contains only a dummy drom (header only,
* no entries). Hardcode the configuration here.
* USB4 hosts may support reading DROM through router
* operations.
*/
tb_drom_read_uid_only(sw, &sw->uid);
if (tb_switch_is_usb4(sw)) {
usb4_switch_read_uid(sw, &sw->uid);
if (!usb4_copy_host_drom(sw, &size))
goto parse;
} else {
/*
* The root switch contains only a dummy drom
* (header only, no entries). Hardcode the
* configuration here.
*/
tb_drom_read_uid_only(sw, &sw->uid);
}

return 0;
}

res = tb_eeprom_read_n(sw, 14, (u8 *) &size, 2);
res = tb_drom_read_n(sw, 14, (u8 *) &size, 2);
if (res)
return res;
size &= 0x3ff;
Expand All @@ -533,7 +576,7 @@ int tb_drom_read(struct tb_switch *sw)
sw->drom = kzalloc(size, GFP_KERNEL);
if (!sw->drom)
return -ENOMEM;
res = tb_eeprom_read_n(sw, 0, sw->drom, size);
res = tb_drom_read_n(sw, 0, sw->drom, size);
if (res)
goto err;

Expand Down
3 changes: 3 additions & 0 deletions drivers/thunderbolt/nhi.c
Original file line number Diff line number Diff line change
Expand Up @@ -1271,6 +1271,9 @@ static struct pci_device_id nhi_ids[] = {
{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_ICL_NHI1),
.driver_data = (kernel_ulong_t)&icl_nhi_ops },

/* Any USB4 compliant host */
{ PCI_DEVICE_CLASS(PCI_CLASS_SERIAL_USB_USB4, ~0) },

{ 0,}
};

Expand Down
2 changes: 2 additions & 0 deletions drivers/thunderbolt/nhi.h
Original file line number Diff line number Diff line change
Expand Up @@ -74,4 +74,6 @@ extern const struct tb_nhi_ops icl_nhi_ops;
#define PCI_DEVICE_ID_INTEL_ICL_NHI1 0x8a0d
#define PCI_DEVICE_ID_INTEL_ICL_NHI0 0x8a17

#define PCI_CLASS_SERIAL_USB_USB4 0x0c0340

#endif
Loading

0 comments on commit b040798

Please sign in to comment.