int usb4_dp_port_requested_bandwidth(struct tb_port *port);
int usb4_pci_port_set_ext_encapsulation(struct tb_port *port, bool enable);
+int usb4_pci_port_ltssm_state(struct tb_port *port);
static inline bool tb_is_usb4_port_device(const struct device *dev)
{
/* PCIe adapter registers */
#define ADP_PCIE_CS_0 0x00
+#define ADP_PCIE_CS_0_LTSSM_MASK GENMASK(28, 25)
#define ADP_PCIE_CS_0_PE BIT(31)
#define ADP_PCIE_CS_1 0x01
#define ADP_PCIE_CS_1_EE BIT(0)
+enum tb_pcie_ltssm_state {
+ USB4_PCIE_LTSSM_DETECT,
+ USB4_PCIE_LTSSM_POLLING,
+ USB4_PCIE_LTSSM_CONFIG,
+ USB4_PCIE_LTSSM_CONFIG_IDLE,
+ USB4_PCIE_LTSSM_RECOVERY,
+ USB4_PCIE_LTSSM_RECOVERY_IDLE,
+ USB4_PCIE_LTSSM_L0,
+ USB4_PCIE_LTSSM_L1,
+ USB4_PCIE_LTSSM_L2,
+ USB4_PCIE_LTSSM_DISABLED,
+ USB4_PCIE_LTSSM_HOT_RESET,
+};
+
/* USB adapter registers */
#define ADP_USB3_CS_0 0x00
#define ADP_USB3_CS_0_V BIT(30)
tunnel->src_port, tunnel->dst_port);
}
+static int tb_pci_port_ltssm_state_detect(struct tb_port *port)
+{
+ ktime_t timeout = ktime_add_ms(ktime_get(), 500);
+
+ do {
+ int ret;
+
+ ret = usb4_pci_port_ltssm_state(port);
+ if (ret < 0)
+ return ret;
+ if (ret == USB4_PCIE_LTSSM_DETECT)
+ return 0;
+
+ fsleep(50);
+ } while (ktime_before(ktime_get(), timeout));
+
+ return -ETIMEDOUT;
+}
+
+static int tb_pci_pre_activate(struct tb_tunnel *tunnel)
+{
+ struct tb_port *down = tunnel->src_port;
+ struct tb_port *up = tunnel->dst_port;
+ int ret;
+
+ ret = tb_switch_is_usb4(down->sw) ?
+ tb_pci_port_ltssm_state_detect(down) : 0;
+ if (ret)
+ return ret;
+
+ return tb_switch_is_usb4(up->sw) ?
+ tb_pci_port_ltssm_state_detect(up) : 0;
+}
+
static int tb_pci_set_ext_encapsulation(struct tb_tunnel *tunnel, bool enable)
{
struct tb_port *port = tb_upstream_port(tunnel->dst_port->sw);
if (!tunnel)
return NULL;
+ tunnel->pre_activate = tb_pci_pre_activate;
tunnel->activate = tb_pci_activate;
tunnel->src_port = down;
tunnel->dst_port = up;
return tb_port_write(port, &val, TB_CFG_PORT,
port->cap_adap + ADP_PCIE_CS_1, 1);
}
+
+/**
+ * usb4_pci_port_ltssm_state() - Read PCIe adapter LTSSM state
+ * @port: PCIe adapter
+ *
+ * Return:
+ * * LTSSM state of @port.
+ * * Negative errno - On failure.
+ */
+int usb4_pci_port_ltssm_state(struct tb_port *port)
+{
+ u32 val;
+ int ret;
+
+ if (!tb_port_is_pcie_down(port) && !tb_port_is_pcie_up(port))
+ return -EINVAL;
+
+ ret = tb_port_read(port, &val, TB_CFG_PORT,
+ port->cap_adap + ADP_PCIE_CS_0, 1);
+ if (ret)
+ return ret;
+
+ return FIELD_GET(ADP_PCIE_CS_0_LTSSM_MASK, val);
+}