diff options
-rw-r--r-- | drivers/thunderbolt/Makefile | 2 | ||||
-rw-r--r-- | drivers/thunderbolt/lc.c | 21 | ||||
-rw-r--r-- | drivers/thunderbolt/switch.c | 21 | ||||
-rw-r--r-- | drivers/thunderbolt/tb.h | 3 | ||||
-rw-r--r-- | drivers/thunderbolt/tb_regs.h | 2 |
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 @@ | |||
1 | obj-${CONFIG_THUNDERBOLT} := thunderbolt.o | 1 | obj-${CONFIG_THUNDERBOLT} := thunderbolt.o |
2 | thunderbolt-objs := nhi.o ctl.o tb.o switch.o cap.o path.o tunnel_pci.o eeprom.o | 2 | thunderbolt-objs := nhi.o ctl.o tb.o switch.o cap.o path.o tunnel_pci.o eeprom.o |
3 | thunderbolt-objs += domain.o dma_port.o icm.o property.o xdomain.o | 3 | thunderbolt-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 | */ | ||
16 | int 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) | |||
1278 | static int tb_switch_set_uuid(struct tb_switch *sw) | 1282 | static 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 | ||
1315 | static int tb_switch_add_dma_port(struct tb_switch *sw) | 1314 | static 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); | |||
462 | int tb_drom_read(struct tb_switch *sw); | 464 | int tb_drom_read(struct tb_switch *sw); |
463 | int tb_drom_read_uid_only(struct tb_switch *sw, u64 *uid); | 465 | int tb_drom_read_uid_only(struct tb_switch *sw, u64 *uid); |
464 | 466 | ||
467 | int tb_lc_read_uuid(struct tb_switch *sw, u32 *uuid); | ||
465 | 468 | ||
466 | static inline int tb_route_length(u64 route) | 469 | static 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 |