summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/thunderbolt/Makefile2
-rw-r--r--drivers/thunderbolt/lc.c21
-rw-r--r--drivers/thunderbolt/switch.c21
-rw-r--r--drivers/thunderbolt/tb.h3
-rw-r--r--drivers/thunderbolt/tb_regs.h2
5 files changed, 37 insertions, 12 deletions
diff --git a/drivers/thunderbolt/Makefile b/drivers/thunderbolt/Makefile
index f2f0de27252b..8531f15d3b3c 100644
--- a/drivers/thunderbolt/Makefile
+++ b/drivers/thunderbolt/Makefile
@@ -1,3 +1,3 @@
1obj-${CONFIG_THUNDERBOLT} := thunderbolt.o 1obj-${CONFIG_THUNDERBOLT} := thunderbolt.o
2thunderbolt-objs := nhi.o ctl.o tb.o switch.o cap.o path.o tunnel_pci.o eeprom.o 2thunderbolt-objs := nhi.o ctl.o tb.o switch.o cap.o path.o tunnel_pci.o eeprom.o
3thunderbolt-objs += domain.o dma_port.o icm.o property.o xdomain.o 3thunderbolt-objs += domain.o dma_port.o icm.o property.o xdomain.o lc.o
diff --git a/drivers/thunderbolt/lc.c b/drivers/thunderbolt/lc.c
new file mode 100644
index 000000000000..2134a55ed837
--- /dev/null
+++ b/drivers/thunderbolt/lc.c
@@ -0,0 +1,21 @@
1// SPDX-License-Identifier: GPL-2.0
2/*
3 * Thunderbolt link controller support
4 *
5 * Copyright (C) 2019, Intel Corporation
6 * Author: Mika Westerberg <mika.westerberg@linux.intel.com>
7 */
8
9#include "tb.h"
10
11/**
12 * tb_lc_read_uuid() - Read switch UUID from link controller common register
13 * @sw: Switch whose UUID is read
14 * @uuid: UUID is placed here
15 */
16int tb_lc_read_uuid(struct tb_switch *sw, u32 *uuid)
17{
18 if (!sw->cap_lc)
19 return -EINVAL;
20 return tb_sw_read(sw, uuid, TB_CFG_SWITCH, sw->cap_lc + TB_LC_FUSE, 4);
21}
diff --git a/drivers/thunderbolt/switch.c b/drivers/thunderbolt/switch.c
index 1e29c06947af..63ff4c753d89 100644
--- a/drivers/thunderbolt/switch.c
+++ b/drivers/thunderbolt/switch.c
@@ -1182,6 +1182,10 @@ struct tb_switch *tb_switch_alloc(struct tb *tb, struct device *parent,
1182 } 1182 }
1183 sw->cap_plug_events = cap; 1183 sw->cap_plug_events = cap;
1184 1184
1185 cap = tb_switch_find_vse_cap(sw, TB_VSE_CAP_LINK_CONTROLLER);
1186 if (cap > 0)
1187 sw->cap_lc = cap;
1188
1185 /* Root switch is always authorized */ 1189 /* Root switch is always authorized */
1186 if (!route) 1190 if (!route)
1187 sw->authorized = true; 1191 sw->authorized = true;
@@ -1278,22 +1282,17 @@ int tb_switch_configure(struct tb_switch *sw)
1278static int tb_switch_set_uuid(struct tb_switch *sw) 1282static int tb_switch_set_uuid(struct tb_switch *sw)
1279{ 1283{
1280 u32 uuid[4]; 1284 u32 uuid[4];
1281 int cap, ret; 1285 int ret;
1282 1286
1283 ret = 0;
1284 if (sw->uuid) 1287 if (sw->uuid)
1285 return ret; 1288 return 0;
1286 1289
1287 /* 1290 /*
1288 * The newer controllers include fused UUID as part of link 1291 * The newer controllers include fused UUID as part of link
1289 * controller specific registers 1292 * controller specific registers
1290 */ 1293 */
1291 cap = tb_switch_find_vse_cap(sw, TB_VSE_CAP_LINK_CONTROLLER); 1294 ret = tb_lc_read_uuid(sw, uuid);
1292 if (cap > 0) { 1295 if (ret) {
1293 ret = tb_sw_read(sw, uuid, TB_CFG_SWITCH, cap + 3, 4);
1294 if (ret)
1295 return ret;
1296 } else {
1297 /* 1296 /*
1298 * ICM generates UUID based on UID and fills the upper 1297 * ICM generates UUID based on UID and fills the upper
1299 * two words with ones. This is not strictly following 1298 * two words with ones. This is not strictly following
@@ -1308,8 +1307,8 @@ static int tb_switch_set_uuid(struct tb_switch *sw)
1308 1307
1309 sw->uuid = kmemdup(uuid, sizeof(uuid), GFP_KERNEL); 1308 sw->uuid = kmemdup(uuid, sizeof(uuid), GFP_KERNEL);
1310 if (!sw->uuid) 1309 if (!sw->uuid)
1311 ret = -ENOMEM; 1310 return -ENOMEM;
1312 return ret; 1311 return 0;
1313} 1312}
1314 1313
1315static int tb_switch_add_dma_port(struct tb_switch *sw) 1314static int tb_switch_add_dma_port(struct tb_switch *sw)
diff --git a/drivers/thunderbolt/tb.h b/drivers/thunderbolt/tb.h
index a166265dfcf9..e52d39b25266 100644
--- a/drivers/thunderbolt/tb.h
+++ b/drivers/thunderbolt/tb.h
@@ -63,6 +63,7 @@ struct tb_switch_nvm {
63 * @device_name: Name of the device (or %NULL if not known) 63 * @device_name: Name of the device (or %NULL if not known)
64 * @generation: Switch Thunderbolt generation 64 * @generation: Switch Thunderbolt generation
65 * @cap_plug_events: Offset to the plug events capability (%0 if not found) 65 * @cap_plug_events: Offset to the plug events capability (%0 if not found)
66 * @cap_lc: Offset to the link controller capability (%0 if not found)
66 * @is_unplugged: The switch is going away 67 * @is_unplugged: The switch is going away
67 * @drom: DROM of the switch (%NULL if not found) 68 * @drom: DROM of the switch (%NULL if not found)
68 * @nvm: Pointer to the NVM if the switch has one (%NULL otherwise) 69 * @nvm: Pointer to the NVM if the switch has one (%NULL otherwise)
@@ -96,6 +97,7 @@ struct tb_switch {
96 const char *device_name; 97 const char *device_name;
97 unsigned int generation; 98 unsigned int generation;
98 int cap_plug_events; 99 int cap_plug_events;
100 int cap_lc;
99 bool is_unplugged; 101 bool is_unplugged;
100 u8 *drom; 102 u8 *drom;
101 struct tb_switch_nvm *nvm; 103 struct tb_switch_nvm *nvm;
@@ -462,6 +464,7 @@ bool tb_path_is_invalid(struct tb_path *path);
462int tb_drom_read(struct tb_switch *sw); 464int tb_drom_read(struct tb_switch *sw);
463int tb_drom_read_uid_only(struct tb_switch *sw, u64 *uid); 465int tb_drom_read_uid_only(struct tb_switch *sw, u64 *uid);
464 466
467int tb_lc_read_uuid(struct tb_switch *sw, u32 *uuid);
465 468
466static inline int tb_route_length(u64 route) 469static inline int tb_route_length(u64 route)
467{ 470{
diff --git a/drivers/thunderbolt/tb_regs.h b/drivers/thunderbolt/tb_regs.h
index 6f1ff04ee195..4895ae9f0b40 100644
--- a/drivers/thunderbolt/tb_regs.h
+++ b/drivers/thunderbolt/tb_regs.h
@@ -237,5 +237,7 @@ struct tb_regs_hop {
237 u32 unknown3:4; /* set to zero */ 237 u32 unknown3:4; /* set to zero */
238} __packed; 238} __packed;
239 239
240/* Common link controller registers */
241#define TB_LC_FUSE 0x03
240 242
241#endif 243#endif