summaryrefslogtreecommitdiffstats
path: root/drivers/thunderbolt
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/thunderbolt')
-rw-r--r--drivers/thunderbolt/cap.c69
-rw-r--r--drivers/thunderbolt/tb.h10
2 files changed, 62 insertions, 17 deletions
diff --git a/drivers/thunderbolt/cap.c b/drivers/thunderbolt/cap.c
index 9553305c63ea..a58585b4e6d9 100644
--- a/drivers/thunderbolt/cap.c
+++ b/drivers/thunderbolt/cap.c
@@ -13,6 +13,7 @@
#define CAP_OFFSET_MAX 0xff
#define VSE_CAP_OFFSET_MAX 0xffff
+#define TMU_ACCESS_EN BIT(20)
struct tb_cap_any {
union {
@@ -22,28 +23,38 @@ struct tb_cap_any {
};
} __packed;
-/**
- * tb_port_find_cap() - Find port capability
- * @port: Port to find the capability for
- * @cap: Capability to look
- *
- * Returns offset to start of capability or %-ENOENT if no such
- * capability was found. Negative errno is returned if there was an
- * error.
- */
-int tb_port_find_cap(struct tb_port *port, enum tb_port_cap cap)
+static int tb_port_enable_tmu(struct tb_port *port, bool enable)
{
- u32 offset;
+ struct tb_switch *sw = port->sw;
+ u32 value, offset;
+ int ret;
/*
- * DP out adapters claim to implement TMU capability but in
- * reality they do not so we hard code the adapter specific
- * capability offset here.
+ * Legacy devices need to have TMU access enabled before port
+ * space can be fully accessed.
*/
- if (port->config.type == TB_TYPE_DP_HDMI_OUT)
- offset = 0x39;
+ if (tb_switch_is_lr(sw))
+ offset = 0x26;
+ else if (tb_switch_is_er(sw))
+ offset = 0x2a;
+ else
+ return 0;
+
+ ret = tb_sw_read(sw, &value, TB_CFG_SWITCH, offset, 1);
+ if (ret)
+ return ret;
+
+ if (enable)
+ value |= TMU_ACCESS_EN;
else
- offset = 0x1;
+ value &= ~TMU_ACCESS_EN;
+
+ return tb_sw_write(sw, &value, TB_CFG_SWITCH, offset, 1);
+}
+
+static int __tb_port_find_cap(struct tb_port *port, enum tb_port_cap cap)
+{
+ u32 offset = 1;
do {
struct tb_cap_any header;
@@ -62,6 +73,30 @@ int tb_port_find_cap(struct tb_port *port, enum tb_port_cap cap)
return -ENOENT;
}
+/**
+ * tb_port_find_cap() - Find port capability
+ * @port: Port to find the capability for
+ * @cap: Capability to look
+ *
+ * Returns offset to start of capability or %-ENOENT if no such
+ * capability was found. Negative errno is returned if there was an
+ * error.
+ */
+int tb_port_find_cap(struct tb_port *port, enum tb_port_cap cap)
+{
+ int ret;
+
+ ret = tb_port_enable_tmu(port, true);
+ if (ret)
+ return ret;
+
+ ret = __tb_port_find_cap(port, cap);
+
+ tb_port_enable_tmu(port, false);
+
+ return ret;
+}
+
static int tb_switch_find_cap(struct tb_switch *sw, enum tb_switch_cap cap)
{
int offset = sw->config.first_cap_offset;
diff --git a/drivers/thunderbolt/tb.h b/drivers/thunderbolt/tb.h
index 93c1ea21feeb..a166265dfcf9 100644
--- a/drivers/thunderbolt/tb.h
+++ b/drivers/thunderbolt/tb.h
@@ -436,6 +436,16 @@ static inline struct tb_switch *tb_to_switch(struct device *dev)
return NULL;
}
+static inline bool tb_switch_is_lr(const struct tb_switch *sw)
+{
+ return sw->config.device_id == PCI_DEVICE_ID_INTEL_LIGHT_RIDGE;
+}
+
+static inline bool tb_switch_is_er(const struct tb_switch *sw)
+{
+ return sw->config.device_id == PCI_DEVICE_ID_INTEL_EAGLE_RIDGE;
+}
+
int tb_wait_for_port(struct tb_port *port, bool wait_if_unplugged);
int tb_port_add_nfc_credits(struct tb_port *port, int credits);
int tb_port_clear_counter(struct tb_port *port, int counter);