xref: /freebsd/sys/dev/thunderbolt/nhi_var.h (revision c4f32e7a354eeebd503714d0e2be8be87562df1c)
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3  *
4  * Copyright (c) 2022 Scott Long
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26  * SUCH DAMAGE.
27  *
28  * Thunderbolt 3 / Native Host Interface driver variables
29  */
30 
31 #ifndef _NHI_VAR
32 #define _NHI_VAR
33 
34 MALLOC_DECLARE(M_NHI);
35 
36 #define NHI_MSIX_MAX		32
37 #define NHI_RING0_TX_DEPTH	16
38 #define NHI_RING0_RX_DEPTH	16
39 #define NHI_DEFAULT_NUM_RINGS	1
40 #define NHI_MAX_NUM_RINGS	32	/* XXX 2? */
41 #define NHI_RING0_FRAME_SIZE	256
42 #define NHI_MAILBOX_TIMEOUT	15
43 
44 #define NHI_CMD_TIMEOUT		3	/* 3 seconds */
45 
46 struct nhi_softc;
47 struct nhi_ring_pair;
48 struct nhi_intr_tracker;
49 struct nhi_cmd_frame;
50 struct hcm_softc;
51 struct router_softc;
52 
53 struct nhi_cmd_frame {
54 	TAILQ_ENTRY(nhi_cmd_frame)	cm_link;
55 	uint32_t		*data;
56 	bus_addr_t		data_busaddr;
57 	u_int			req_len;
58 	uint16_t		flags;
59 #define CMD_MAPPED		(1 << 0)
60 #define CMD_POLLED		(1 << 1)
61 #define CMD_REQ_COMPLETE	(1 << 2)
62 #define CMD_RESP_COMPLETE	(1 << 3)
63 #define CMD_RESP_OVERRUN	(1 << 4)
64 	uint16_t		retries;
65 	uint16_t		pdf;
66 	uint16_t		idx;
67 
68 	void			*context;
69 	u_int			timeout;
70 
71 	uint32_t		*resp_buffer;
72 	u_int			resp_len;
73 };
74 
75 #define NHI_RING_NAMELEN	16
76 struct nhi_ring_pair {
77 	struct nhi_softc	*sc;
78 
79 	union nhi_ring_desc	*tx_ring;
80 	union nhi_ring_desc	*rx_ring;
81 
82 	uint16_t		tx_pi;
83 	uint16_t		tx_ci;
84 	uint16_t		rx_pi;
85 	uint16_t		rx_ci;
86 
87 	uint16_t		rx_pici_reg;
88 	uint16_t		tx_pici_reg;
89 
90 	struct nhi_cmd_frame	**rx_cmd_ring;
91 	struct nhi_cmd_frame	**tx_cmd_ring;
92 
93 	struct mtx		mtx;
94 	char			name[NHI_RING_NAMELEN];
95 	struct nhi_intr_tracker	*tracker;
96 	SLIST_ENTRY(nhi_ring_pair)	ring_link;
97 
98 	TAILQ_HEAD(, nhi_cmd_frame)	tx_head;
99 	TAILQ_HEAD(, nhi_cmd_frame)	rx_head;
100 
101 	uint16_t		tx_ring_depth;
102 	uint16_t		tx_ring_mask;
103 	uint16_t		rx_ring_depth;
104 	uint16_t		rx_ring_mask;
105 	uint16_t		rx_buffer_size;
106 	u_char			ring_num;
107 
108 	bus_dma_tag_t		ring_dmat;
109 	bus_dmamap_t		ring_map;
110 	void			*ring;
111 	bus_addr_t		tx_ring_busaddr;
112 	bus_addr_t		rx_ring_busaddr;
113 
114 	bus_dma_tag_t		frames_dmat;
115 	bus_dmamap_t		frames_map;
116 	void			*frames;
117 	bus_addr_t		tx_frames_busaddr;
118 	bus_addr_t		rx_frames_busaddr;
119 };
120 
121 /* PDF-indexed array of dispatch routines for interrupts */
122 typedef void (nhi_ring_cb_t)(void *, union nhi_ring_desc *,
123     struct nhi_cmd_frame *);
124 struct nhi_pdf_dispatch {
125 	nhi_ring_cb_t		*cb;
126 	void			*context;
127 };
128 
129 struct nhi_intr_tracker {
130 	struct nhi_softc	*sc;
131 	struct nhi_ring_pair	*ring;
132 	struct nhi_pdf_dispatch	txpdf[16];
133 	struct nhi_pdf_dispatch	rxpdf[16];
134 	u_int			vector;
135 };
136 
137 struct nhi_softc {
138 	device_t		dev;
139 	device_t		ufp;
140 	u_int			debug;
141 	u_int			hwflags;
142 #define NHI_TYPE_UNKNOWN	0x00
143 #define NHI_TYPE_USB4		0x0f
144 #define NHI_TYPE_MASK		0x0f
145 #define NHI_MBOX_BUSY		0x10
146 	struct hcm_softc	*hcm;
147 	struct router_softc	*root_rsc;
148 
149 	struct nhi_ring_pair	*ring0;
150 	struct nhi_intr_tracker	*intr_trackers;
151 
152 	uint16_t		path_count;
153 	uint16_t		max_ring_count;
154 
155 	struct mtx		nhi_mtx;
156 	SLIST_HEAD(, nhi_ring_pair)	ring_list;
157 
158 	int			msix_count;
159 	struct resource		*irqs[NHI_MSIX_MAX];
160 	void			*intrhand[NHI_MSIX_MAX];
161 	int			irq_rid[NHI_MSIX_MAX];
162 	struct resource		*irq_pba;
163 	int			irq_pba_rid;
164 	struct resource		*irq_table;
165 	int			irq_table_rid;
166 
167 	struct resource		*regs_resource;
168 	bus_space_handle_t	regs_bhandle;
169 	bus_space_tag_t		regs_btag;
170 	int			regs_rid;
171 
172 	bus_dma_tag_t		parent_dmat;
173 
174 	bus_dma_tag_t		ring0_dmat;
175 	bus_dmamap_t		ring0_map;
176 	void			*ring0_frames;
177 	bus_addr_t		ring0_frames_busaddr;
178 	struct nhi_cmd_frame	*ring0_cmds;
179 
180 	struct sysctl_ctx_list	*sysctl_ctx;
181 	struct sysctl_oid	*sysctl_tree;
182 
183 	struct intr_config_hook	ich;
184 
185 	uint8_t			uuid[16];
186 	uint8_t			lc_uuid[16];
187 
188 	enum {
189 		NHI_VER_1_0,
190 		NHI_VER_2_0,
191 	}			ver;
192 };
193 
194 struct nhi_dispatch {
195 	uint8_t			pdf;
196 	nhi_ring_cb_t		*cb;
197 	void			*context;
198 };
199 
200 #define NHI_IS_USB4(sc)	(((sc)->hwflags & NHI_TYPE_MASK) == NHI_TYPE_USB4)
201 
202 int nhi_pci_configure_interrupts(struct nhi_softc *sc);
203 void nhi_pci_enable_interrupt(struct nhi_ring_pair *r);
204 void nhi_pci_disable_interrupts(struct nhi_softc *sc);
205 void nhi_pci_free_interrupts(struct nhi_softc *sc);
206 int nhi_pci_get_uuid(struct nhi_softc *sc);
207 int nhi_read_lc_mailbox(struct nhi_softc *, u_int reg, uint32_t *val);
208 int nhi_write_lc_mailbox(struct nhi_softc *, u_int reg, uint32_t val);
209 
210 void nhi_get_tunables(struct nhi_softc *);
211 int nhi_attach(struct nhi_softc *);
212 int nhi_detach(struct nhi_softc *);
213 
214 struct nhi_cmd_frame * nhi_alloc_tx_frame(struct nhi_ring_pair *);
215 void nhi_free_tx_frame(struct nhi_ring_pair *, struct nhi_cmd_frame *);
216 
217 int nhi_inmail_cmd(struct nhi_softc *, uint32_t, uint32_t);
218 int nhi_outmail_cmd(struct nhi_softc *, uint32_t *);
219 
220 int nhi_tx_schedule(struct nhi_ring_pair *, struct nhi_cmd_frame *);
221 int nhi_tx_synchronous(struct nhi_ring_pair *, struct nhi_cmd_frame *);
222 void nhi_intr(void *);
223 
224 int nhi_register_pdf(struct nhi_ring_pair *, struct nhi_dispatch *,
225     struct nhi_dispatch *);
226 int nhi_deregister_pdf(struct nhi_ring_pair *, struct nhi_dispatch *,
227     struct nhi_dispatch *);
228 
229 /* Low level read/write MMIO registers */
230 static __inline uint32_t
231 nhi_read_reg(struct nhi_softc *sc, u_int offset)
232 {
233 	return (le32toh(bus_space_read_4(sc->regs_btag, sc->regs_bhandle,
234 	    offset)));
235 }
236 
237 static __inline void
238 nhi_write_reg(struct nhi_softc *sc, u_int offset, uint32_t val)
239 {
240 	bus_space_write_4(sc->regs_btag, sc->regs_bhandle, offset,
241 	    htole32(val));
242 }
243 
244 static __inline struct nhi_cmd_frame *
245 nhi_alloc_tx_frame_locked(struct nhi_ring_pair *r)
246 {
247 	struct nhi_cmd_frame *cmd;
248 
249 	if ((cmd = TAILQ_FIRST(&r->tx_head)) != NULL)
250 		TAILQ_REMOVE(&r->tx_head, cmd, cm_link);
251 	return (cmd);
252 }
253 
254 static __inline void
255 nhi_free_tx_frame_locked(struct nhi_ring_pair *r, struct nhi_cmd_frame *cmd)
256 {
257 	/* Clear all flags except for MAPPED */
258 	cmd->flags &= CMD_MAPPED;
259 	cmd->resp_buffer = NULL;
260 	TAILQ_INSERT_TAIL(&r->tx_head, cmd, cm_link);
261 }
262 
263 #endif /* _NHI_VAR */
264