Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

thunderbolt: Add tb_regs.h

Every thunderbolt device consists (logically) of a switch with multiple
ports. Every port contains up to four config regions (HOPS, PORT,
SWITCH, COUNTERS) which are used to configure the device.

The tb_regs.h file contains all known registers and capabilities from
these config regions.

Signed-off-by: Andreas Noever <andreas.noever@gmail.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

authored by

Andreas Noever and committed by
Greg Kroah-Hartman
7adf6097 d6cc51cd

+218
+5
drivers/thunderbolt/tb.c
··· 9 9 #include <linux/delay.h> 10 10 11 11 #include "tb.h" 12 + #include "tb_regs.h" 12 13 13 14 /* hotplug handling */ 14 15 ··· 100 99 struct tb *thunderbolt_alloc_and_start(struct tb_nhi *nhi) 101 100 { 102 101 struct tb *tb; 102 + 103 + BUILD_BUG_ON(sizeof(struct tb_regs_switch_header) != 5 * 4); 104 + BUILD_BUG_ON(sizeof(struct tb_regs_port_header) != 8 * 4); 105 + BUILD_BUG_ON(sizeof(struct tb_regs_hop) != 2 * 4); 103 106 104 107 tb = kzalloc(sizeof(*tb), GFP_KERNEL); 105 108 if (!tb)
+213
drivers/thunderbolt/tb_regs.h
··· 1 + /* 2 + * Thunderbolt Cactus Ridge driver - Port/Switch config area registers 3 + * 4 + * Every thunderbolt device consists (logically) of a switch with multiple 5 + * ports. Every port contains up to four config regions (HOPS, PORT, SWITCH, 6 + * COUNTERS) which are used to configure the device. 7 + * 8 + * Copyright (c) 2014 Andreas Noever <andreas.noever@gmail.com> 9 + */ 10 + 11 + #ifndef _TB_REGS 12 + #define _TB_REGS 13 + 14 + #include <linux/types.h> 15 + 16 + 17 + #define TB_ROUTE_SHIFT 8 /* number of bits in a port entry of a route */ 18 + 19 + 20 + /* 21 + * TODO: should be 63? But we do not know how to receive frames larger than 256 22 + * bytes at the frame level. (header + checksum = 16, 60*4 = 240) 23 + */ 24 + #define TB_MAX_CONFIG_RW_LENGTH 60 25 + 26 + enum tb_cap { 27 + TB_CAP_PHY = 0x0001, 28 + TB_CAP_TIME1 = 0x0003, 29 + TB_CAP_PCIE = 0x0004, 30 + TB_CAP_I2C = 0x0005, 31 + TB_CAP_PLUG_EVENTS = 0x0105, /* also EEPROM */ 32 + TB_CAP_TIME2 = 0x0305, 33 + TB_CAL_IECS = 0x0405, 34 + TB_CAP_LINK_CONTROLLER = 0x0605, /* also IECS */ 35 + }; 36 + 37 + enum tb_port_state { 38 + TB_PORT_DISABLED = 0, /* tb_cap_phy.disable == 1 */ 39 + TB_PORT_CONNECTING = 1, /* retry */ 40 + TB_PORT_UP = 2, 41 + TB_PORT_UNPLUGGED = 7, 42 + }; 43 + 44 + /* capability headers */ 45 + 46 + struct tb_cap_basic { 47 + u8 next; 48 + /* enum tb_cap cap:8; prevent "narrower than values of its type" */ 49 + u8 cap; /* if cap == 0x05 then we have a extended capability */ 50 + } __packed; 51 + 52 + struct tb_cap_extended_short { 53 + u8 next; /* if next and length are zero then we have a long cap */ 54 + enum tb_cap cap:16; 55 + u8 length; 56 + } __packed; 57 + 58 + struct tb_cap_extended_long { 59 + u8 zero1; 60 + enum tb_cap cap:16; 61 + u8 zero2; 62 + u16 next; 63 + u16 length; 64 + } __packed; 65 + 66 + /* capabilities */ 67 + 68 + struct tb_cap_link_controller { 69 + struct tb_cap_extended_long cap_header; 70 + u32 count:4; /* number of link controllers */ 71 + u32 unknown1:4; 72 + u32 base_offset:8; /* 73 + * offset (into this capability) of the configuration 74 + * area of the first link controller 75 + */ 76 + u32 length:12; /* link controller configuration area length */ 77 + u32 unknown2:4; /* TODO check that length is correct */ 78 + } __packed; 79 + 80 + struct tb_cap_phy { 81 + struct tb_cap_basic cap_header; 82 + u32 unknown1:16; 83 + u32 unknown2:14; 84 + bool disable:1; 85 + u32 unknown3:11; 86 + enum tb_port_state state:4; 87 + u32 unknown4:2; 88 + } __packed; 89 + 90 + struct tb_eeprom_ctl { 91 + bool clock:1; /* send pulse to transfer one bit */ 92 + bool access_low:1; /* set to 0 before access */ 93 + bool data_out:1; /* to eeprom */ 94 + bool data_in:1; /* from eeprom */ 95 + bool access_high:1; /* set to 1 before access */ 96 + bool not_present:1; /* should be 0 */ 97 + bool unknown1:1; 98 + bool present:1; /* should be 1 */ 99 + u32 unknown2:24; 100 + } __packed; 101 + 102 + struct tb_cap_plug_events { 103 + struct tb_cap_extended_short cap_header; 104 + u32 __unknown1:2; 105 + u32 plug_events:5; 106 + u32 __unknown2:25; 107 + u32 __unknown3; 108 + u32 __unknown4; 109 + struct tb_eeprom_ctl eeprom_ctl; 110 + u32 __unknown5[7]; 111 + u32 drom_offset; /* 32 bit register, but eeprom addresses are 16 bit */ 112 + } __packed; 113 + 114 + /* device headers */ 115 + 116 + /* Present on port 0 in TB_CFG_SWITCH at address zero. */ 117 + struct tb_regs_switch_header { 118 + /* DWORD 0 */ 119 + u16 vendor_id; 120 + u16 device_id; 121 + /* DWORD 1 */ 122 + u32 first_cap_offset:8; 123 + u32 upstream_port_number:6; 124 + u32 max_port_number:6; 125 + u32 depth:3; 126 + u32 __unknown1:1; 127 + u32 revision:8; 128 + /* DWORD 2 */ 129 + u32 route_lo; 130 + /* DWORD 3 */ 131 + u32 route_hi:31; 132 + bool enabled:1; 133 + /* DWORD 4 */ 134 + u32 plug_events_delay:8; /* 135 + * RW, pause between plug events in 136 + * milliseconds. Writing 0x00 is interpreted 137 + * as 255ms. 138 + */ 139 + u32 __unknown4:16; 140 + u32 thunderbolt_version:8; 141 + } __packed; 142 + 143 + enum tb_port_type { 144 + TB_TYPE_INACTIVE = 0x000000, 145 + TB_TYPE_PORT = 0x000001, 146 + TB_TYPE_NHI = 0x000002, 147 + /* TB_TYPE_ETHERNET = 0x020000, lower order bits are not known */ 148 + /* TB_TYPE_SATA = 0x080000, lower order bits are not known */ 149 + TB_TYPE_DP_HDMI_IN = 0x0e0101, 150 + TB_TYPE_DP_HDMI_OUT = 0x0e0102, 151 + TB_TYPE_PCIE_DOWN = 0x100101, 152 + TB_TYPE_PCIE_UP = 0x100102, 153 + /* TB_TYPE_USB = 0x200000, lower order bits are not known */ 154 + }; 155 + 156 + /* Present on every port in TB_CF_PORT at address zero. */ 157 + struct tb_regs_port_header { 158 + /* DWORD 0 */ 159 + u16 vendor_id; 160 + u16 device_id; 161 + /* DWORD 1 */ 162 + u32 first_cap_offset:8; 163 + u32 max_counters:11; 164 + u32 __unknown1:5; 165 + u32 revision:8; 166 + /* DWORD 2 */ 167 + enum tb_port_type type:24; 168 + u32 thunderbolt_version:8; 169 + /* DWORD 3 */ 170 + u32 __unknown2:20; 171 + u32 port_number:6; 172 + u32 __unknown3:6; 173 + /* DWORD 4 */ 174 + u32 nfc_credits; 175 + /* DWORD 5 */ 176 + u32 max_in_hop_id:11; 177 + u32 max_out_hop_id:11; 178 + u32 __unkown4:10; 179 + /* DWORD 6 */ 180 + u32 __unknown5; 181 + /* DWORD 7 */ 182 + u32 __unknown6; 183 + 184 + } __packed; 185 + 186 + /* Hop register from TB_CFG_HOPS. 8 byte per entry. */ 187 + struct tb_regs_hop { 188 + /* DWORD 0 */ 189 + u32 next_hop:11; /* 190 + * hop to take after sending the packet through 191 + * out_port (on the incoming port of the next switch) 192 + */ 193 + u32 out_port:6; /* next port of the path (on the same switch) */ 194 + u32 initial_credits:8; 195 + u32 unknown1:6; /* set to zero */ 196 + bool enable:1; 197 + 198 + /* DWORD 1 */ 199 + u32 weight:4; 200 + u32 unknown2:4; /* set to zero */ 201 + u32 priority:3; 202 + bool drop_packages:1; 203 + u32 counter:11; /* index into TB_CFG_COUNTERS on this port */ 204 + bool counter_enable:1; 205 + bool ingress_fc:1; 206 + bool egress_fc:1; 207 + bool ingress_shared_buffer:1; 208 + bool egress_shared_buffer:1; 209 + u32 unknown3:4; /* set to zero */ 210 + } __packed; 211 + 212 + 213 + #endif