xref: /illumos-gate/usr/src/uts/common/io/i2c/nexus/i2cnex.h (revision 32002227574cf0a435dc03de622191ca53724f0a)
1 /*
2  * This file and its contents are supplied under the terms of the
3  * Common Development and Distribution License ("CDDL"), version 1.0.
4  * You may only use this file in accordance with the terms of version
5  * 1.0 of the CDDL.
6  *
7  * A full copy of the text of the CDDL should have accompanied this
8  * source.  A copy of the CDDL is also available via the Internet at
9  * http://www.illumos.org/license/CDDL.
10  */
11 
12 /*
13  * Copyright 2025 Oxide Computer Company
14  */
15 
16 #ifndef _I2CNEX_H
17 #define	_I2CNEX_H
18 
19 /*
20  * Internal definitions for the i2c nexus driver.
21  */
22 
23 #include <sys/id_space.h>
24 #include <sys/avl.h>
25 #include <sys/list.h>
26 #include <sys/types.h>
27 #include <sys/mkdev.h>
28 #include <sys/i2c/controller.h>
29 #include <sys/i2c/client.h>
30 #include <sys/i2c/mux.h>
31 #include <sys/i2c/ioctl.h>
32 
33 #ifdef __cplusplus
34 extern "C" {
35 #endif
36 
37 /*
38  * This is the maximum number of ports we'll support on a controller or switch
39  * today.
40  */
41 #define	I2C_MAX_PORTS	16
42 
43 /*
44  * We split our minor range in two. There is a range that is used for devices
45  * and a range that is used for users. The range for devices is in the range [1,
46  * MAXMIN32], where as users start at MAXMIN32+1 and are given up to a million
47  * entries.
48  */
49 #define	I2C_DEV_MINOR_MIN	1
50 #define	I2C_DEV_MINOR_MAX	MAXMIN32
51 #define	I2C_USER_MINOR_MIN	(MAXMIN32 + 1)
52 #define	I2C_USER_MINOR_MAX	(MAXMIN32 + (2 << 19))
53 
54 /*
55  * Global data that tracks minor mapping and related.
56  */
57 typedef struct i2cnex_minors {
58 	kmutex_t im_mutex;
59 	id_space_t *im_ids;
60 	id_space_t *im_user_ids;
61 	avl_tree_t im_nexi;
62 	avl_tree_t im_users;
63 	list_t im_roots;
64 } i2cnex_minors_t;
65 
66 /*
67  * Forward decls for various things.
68  */
69 typedef struct i2c_root i2c_root_t;
70 typedef struct i2c_ctrl i2c_ctrl_t;
71 typedef struct i2c_port i2c_port_t;
72 typedef struct i2c_dev i2c_dev_t;
73 typedef struct i2c_mux i2c_mux_t;
74 typedef struct i2c_nexus i2c_nexus_t;
75 
76 /*
77  * Address tracking structures. See i2cnex_addr.c theory statement for more
78  * information.
79  */
80 typedef struct i2c_addr_track {
81 	bool at_downstream[1 << 10];
82 	uint8_t at_refcnt[1 << 10];
83 	major_t at_major[1 << 10];
84 } i2c_addr_track_t;
85 
86 /*
87  * This represents a port on a mux or a controller. Device IDs are unique
88  * downstream of a port.
89  */
90 struct i2c_port {
91 	uint32_t ip_portno;
92 	/*
93 	 * This is used to indicate the number of device's that exist on a port
94 	 * below this one. The number of devices that are on this port is just
95 	 * an avl_numnodes() call on ip_devices.
96 	 */
97 	uint32_t ip_ndevs_ds;
98 	i2c_nexus_t *ip_nex;
99 	i2c_addr_track_t ip_track_7b;
100 	avl_tree_t ip_devices;
101 	list_node_t ip_ctrl_link;
102 };
103 
104 /*
105  * This represents a single device on the i2c bus.
106  */
107 struct i2c_dev {
108 	avl_node_t id_link;
109 	i2c_addr_t id_addr;
110 	char **id_ucompat;
111 	uint_t id_nucompat;
112 	i2c_nexus_t *id_nex;
113 	i2c_mux_t *id_mux;
114 	list_t id_clients;
115 };
116 
117 /*
118  * This represents information about a single mux. This is used when a device
119  * registers with the mux framework.
120  */
121 struct i2c_mux {
122 	i2c_nexus_t *im_nex;
123 	const i2c_mux_ops_t *im_ops;
124 	void *im_drv;
125 	uint32_t im_nports;
126 	/*
127 	 * This data is all protected by the controller lock after
128 	 * initialization.
129 	 */
130 	uint32_t im_curport;
131 	i2c_port_t im_ports[I2C_MAX_PORTS];
132 };
133 
134 typedef enum {
135 	I2C_CTRL_MA_NONE,
136 	I2C_CTRL_MA_DESELECT,
137 	I2C_CTRL_MA_UPDATE
138 } i2c_ctrl_mux_act_t;
139 
140 typedef struct i2c_ctrl_lock {
141 	kmutex_t cl_mutex;
142 	i2c_txn_t *cl_owner;
143 	list_t cl_waiters;
144 	/*
145 	 * The following members are used to track when a nexus operation is
146 	 * active. These basically allow a subsequent nexus operation in the
147 	 * same thread to take advantage of the lock. See the locking section
148 	 * in the theory statement for more information.
149 	 */
150 	uintptr_t cl_nexus_thr;
151 	list_t cl_stack;
152 	/*
153 	 * Misc. debugging stats.
154 	 */
155 	uint32_t cl_nlocks;
156 	uint32_t cl_nwait;
157 	uint32_t cl_nnonblock;
158 	uint32_t cl_nsig;
159 	uint32_t cl_nsig_block;
160 	uint32_t cl_nsig_acq;
161 	uint32_t cl_nstack;
162 	uint32_t cl_nnexus;
163 } i2c_ctrl_lock_t;
164 
165 typedef struct i2c_ctrl_limit {
166 	uint32_t lim_i2c_read;
167 	uint32_t lim_i2c_write;
168 	smbus_prop_op_t lim_smbus_ops;
169 	uint32_t lim_smbus_block;
170 } i2c_ctrl_limit_t;
171 
172 /*
173  * This represents an instance of a controller. A controller has independent
174  * controls and settings.
175  */
176 struct i2c_ctrl {
177 	list_node_t ic_link;
178 	i2c_root_t *ic_root;
179 	void *ic_drv;
180 	const i2c_ctrl_ops_t *ic_ops;
181 	i2c_ctrl_type_t ic_type;
182 	i2c_nexus_t *ic_nexus;
183 	uint32_t ic_nports;
184 	i2c_port_t ic_ports[I2C_MAX_PORTS];
185 	i2c_ctrl_lock_t ic_lock;
186 	i2c_ctrl_limit_t ic_limit;
187 	union {
188 		smbus_req_t req_smbus;
189 		i2c_req_t req_i2c;
190 	} ic_reqs;
191 	/*
192 	 * These lists are used to manage and track the set of mux ports that
193 	 * are currently being used on the bus in the order that they exist in
194 	 * the tree. The head of the list will generally be the current port on
195 	 * the bus that's being used. The tail the furthest mux in the tree.
196 	 * When something is in here, it means that traffic will flow down the
197 	 * port. The plan list is used when we're switching between different
198 	 * muxes and want to indicate what the new order will be. See the I/O
199 	 * and Mux Tracking section of the theory statement for more
200 	 * information.
201 	 *
202 	 * The mux state is used to track what mux activity we're actively
203 	 * doing. This is useful because when we activate or deactivate a mux,
204 	 * it'll call back into the mux update logic.
205 	 */
206 	list_t ic_mux_active;
207 	list_t ic_mux_plan;
208 	i2c_ctrl_mux_act_t ic_mux_state;
209 	/*
210 	 * The ic_txn_lock protects the list of i2c_txn_t only. It is not used
211 	 * as part of locking more broadly.
212 	 */
213 	kmutex_t ic_txn_lock;
214 	list_t ic_txns;
215 };
216 
217 typedef enum {
218 	I2C_NEXUS_T_CTRL,
219 	I2C_NEXUS_T_PORT,
220 	I2C_NEXUS_T_DEV,
221 	I2C_NEXUS_T_MUX
222 } i2c_nexus_type_t;
223 
224 typedef enum {
225 	/*
226 	 * This indicates that the nexus is discoverable and present in the
227 	 * global tree.
228 	 */
229 	I2C_NEXUS_F_DISC = 1 << 0
230 } i2c_nexus_flags_t;
231 
232 struct i2c_nexus {
233 	avl_node_t in_avl;
234 	i2c_nexus_type_t in_type;
235 	i2c_nexus_flags_t in_flags;
236 	i2c_ctrl_t *in_ctrl;
237 	char in_name[I2C_NAME_MAX];
238 	char in_addr[I2C_NAME_MAX];
239 	id_t in_minor;
240 	dev_info_t *in_dip;
241 	dev_info_t *in_pdip;
242 	i2c_nexus_t *in_pnex;
243 	union {
244 		i2c_port_t *in_port;
245 		i2c_dev_t *in_dev;
246 		i2c_mux_t *in_mux;
247 	} in_data;
248 };
249 
250 /*
251  * This represents the root of an i2c controller tree.
252  */
253 struct i2c_root {
254 	list_node_t ir_link;
255 	dev_info_t *ir_dip;
256 	kmutex_t ir_mutex;
257 	list_t ir_ctrls;
258 };
259 
260 /*
261  * Various debugging tags that indicate where we were trying to create an i2c
262  * transaction.
263  */
264 typedef enum {
265 	I2C_LOCK_TAG_MUX_REG,
266 	I2C_LOCK_TAG_MUX_UNREG,
267 	I2C_LOCK_TAG_BUS_CONFIG,
268 	I2C_LOCK_TAG_BUS_UNCONFIG,
269 	I2C_LOCK_TAG_DIP_DETACH,
270 	I2C_LOCK_TAG_CLIENT_LOCK,
271 	I2C_LOCK_TAG_CLIENT_ALLOC,
272 	I2C_LOCK_TAG_CLIENT_ADDR,
273 	I2C_LOCK_TAG_CLIENT_DESTROY,
274 	I2C_LOCK_TAG_USER_IO,
275 	I2C_LOCK_TAG_USER_DEV_ADD,
276 	I2C_LOCK_TAG_USER_DEV_INFO,
277 	I2C_LOCK_TAG_USER_DEV_RM,
278 	I2C_LOCK_TAG_USER_PROP_INFO,
279 	I2C_LOCK_TAG_USER_PROP_SET
280 } i2c_txn_tag_t;
281 
282 typedef enum {
283 	I2C_TXN_STATE_UNLOCKED	= 0,
284 	I2C_TXN_STATE_BLOCKED,
285 	I2C_TXN_STATE_ACQUIRED
286 } i2c_txn_state_t;
287 
288 /*
289  * This data structure represents an i2c transaction structure which is used to
290  * wait on and acquire exclusive access to a controller.
291  */
292 typedef struct i2c_txn {
293 	list_node_t txn_link;
294 	list_node_t txn_wait_link;
295 	list_node_t txn_stack_link;
296 	i2c_ctrl_t *txn_ctrl;
297 	kcondvar_t txn_cv;
298 	i2c_txn_state_t txn_state;
299 	i2c_errno_t txn_err;
300 	/*
301 	 * Misc. debugging information. None of this may be relied upon for
302 	 * correct operation of lock information.  The kthread_t and pid that
303 	 * acquired this may not be the same as the one that is actually later
304 	 * performing I/O and using it. Note, that txn_last_change is used for
305 	 * some correctness assertions.
306 	 */
307 	i2c_txn_tag_t txn_tag;
308 	const void *txn_debug;
309 	hrtime_t txn_last_change;
310 	uintptr_t txn_alloc_kthread;
311 	uintptr_t txn_acq_kthread;
312 	pid_t txn_acq_pid;
313 } i2c_txn_t;
314 
315 typedef enum {
316 	/*
317 	 * This flag indicates that this minor currently holds its controller
318 	 * through a persistent ioctl (which isn't quite present). When this is
319 	 * the case, individual I/O operations don't need to acquire and release
320 	 * the bus.
321 	 */
322 	I2C_USER_F_CTRL_LOCK	= 1 << 0,
323 	/*
324 	 * This flag indicates that this minor is actively trying to perform
325 	 * I/O, manipulate the set of devices on the bus, etc. A thread may only
326 	 * hold this for the duration of a single ioctl. The thread that has set
327 	 * this will be noted in the iu_thread member.
328 	 */
329 	I2C_USER_F_ACTIVE	= 1 << 1,
330 	/*
331 	 * This flag indicates that we took the controller lock as part of this
332 	 * operation and therefore need to make sure that we release it. This
333 	 * can only be set if the I2C_USER_F_ACTIVE flag is set.
334 	 */
335 	I2C_USER_F_LOCK		= 1 << 2
336 } i2c_user_flags_t;
337 
338 /*
339  * This tracks information about an individual minor data that a user may have
340  * open. The user-specific information is protected by the corresponding
341  * controller's lock. A given user structure is always tied to some controller
342  * per the i2c_nexus_t pointer.
343  */
344 typedef struct i2c_user {
345 	/*
346 	 * This links the minor open instance in the global im_users. It is only
347 	 * manipulated while the minors im_muex is held.
348 	 */
349 	avl_node_t iu_avl;
350 	/*
351 	 * These values are set at initial creation time and contain information
352 	 * about what device this is actually bound to.
353 	 */
354 	id_t iu_minor;
355 	i2c_nexus_t *iu_nexus;
356 	/*
357 	 * Dynamic data that is protected by the following mutex.
358 	 */
359 	kmutex_t iu_mutex;
360 	i2c_txn_t *iu_txn;
361 	i2c_user_flags_t iu_flags;
362 	uintptr_t iu_thread;
363 } i2c_user_t;
364 
365 typedef enum {
366 
367 	/*
368 	 * Indicates that this client has a claimed and/or shared address that
369 	 * should be released when it is freed and that the address doesn't
370 	 * belong to the device directly.
371 	 */
372 	I2C_CLIENT_F_CLAIM_ADDR		= 1 << 0,
373 	I2C_CLIENT_F_SHARED_ADDR	= 1 << 1,
374 	/*
375 	 * Indicates that the current I/O operation created the transaction for
376 	 * us.
377 	 */
378 	I2C_CLIENT_F_ALLOC_TXN		= 1 << 2
379 } i2c_client_flags_t;
380 
381 /*
382  * Structure used for kernel device driver consumers.
383  */
384 typedef struct i2c_client {
385 	list_node_t icli_dev_link;
386 	dev_info_t *icli_dip;
387 	i2c_addr_t icli_addr;
388 	i2c_dev_t *icli_dev;
389 	i2c_ctrl_t *icli_ctrl;
390 	i2c_port_t *icli_io_port;
391 	/*
392 	 * The icli_mutex is used to protect the fields below.
393 	 */
394 	kmutex_t icli_mutex;
395 	i2c_client_flags_t icli_flags;
396 	list_t icli_regs;
397 	i2c_txn_t *icli_txn;
398 	uintptr_t icli_curthread;
399 	union {
400 		smbus_req_t req_smbus;
401 		i2c_req_t req_i2c;
402 	} icli_reqs;
403 } i2c_client_t;
404 
405 struct i2c_reg_hdl {
406 	list_node_t reg_link;
407 	i2c_client_t *reg_client;
408 	i2c_reg_acc_attr_t reg_attr;
409 	uint32_t reg_max_nread;
410 	uint32_t reg_max_nwrite;
411 };
412 
413 /*
414  * Access to our global data and minor mapping.
415  */
416 extern i2cnex_minors_t i2cnex_minors;
417 
418 /*
419  * Shared bus_ops.
420  */
421 extern struct bus_ops i2c_nex_bus_ops;
422 
423 /*
424  * Misc. internal functions.
425  */
426 extern i2c_root_t *i2c_dip_to_root(dev_info_t *);
427 extern i2c_root_t *i2c_root_init(dev_info_t *);
428 extern void i2c_root_fini(i2c_root_t *);
429 
430 extern i2c_nexus_t *i2cnex_nex_alloc(i2c_nexus_type_t, dev_info_t *,
431     i2c_nexus_t *, const char *, const char *, i2c_ctrl_t *);
432 extern void i2cnex_nex_free(i2c_nexus_t *);
433 extern i2c_nexus_t *i2c_nex_find_by_minor(minor_t);
434 
435 typedef struct {
436 	bool inbc_matched;
437 	ddi_bus_config_op_t inbc_op;
438 	const void *inbc_arg;
439 	int inbc_ret;
440 	char *inbc_dup;
441 	size_t inbc_duplen;
442 	const char *inbc_name;
443 	const char *inbc_addr;
444 } i2c_nex_bus_config_t;
445 
446 extern int i2c_nex_bus_ctl(dev_info_t *, dev_info_t *, ddi_ctl_enum_t, void *,
447     void *);
448 extern bool i2c_nex_bus_config_init(i2c_nex_bus_config_t *, ddi_bus_config_op_t,
449     const void *);
450 extern void i2c_nex_bus_config_fini(i2c_nex_bus_config_t *);
451 extern void i2c_nex_bus_config_one(i2c_nexus_t *, i2c_nex_bus_config_t *);
452 extern void i2c_nex_bus_unconfig_one(i2c_nexus_t *, i2c_nex_bus_config_t *);
453 extern void i2c_nex_dev_cleanup(i2c_nexus_t *);
454 
455 /*
456  * User Character Device Operations
457  */
458 extern int i2c_nex_open(dev_t *, int, int, cred_t *);
459 extern int i2c_nex_ioctl(dev_t, int, intptr_t, int, cred_t *, int *);
460 extern int i2c_nex_close(dev_t, int, int, cred_t *);
461 
462 /*
463  * Error signaling back to clients.
464  */
465 extern bool i2c_error(i2c_error_t *, i2c_errno_t, i2c_ctrl_error_t);
466 extern void i2c_success(i2c_error_t *);
467 
468 /*
469  * Locking operations.
470  */
471 extern i2c_txn_t *i2c_txn_alloc(i2c_ctrl_t *, i2c_txn_tag_t, const void *);
472 extern i2c_errno_t i2c_txn_ctrl_lock(i2c_txn_t *, bool);
473 extern bool i2c_txn_held(i2c_txn_t *);
474 extern void i2c_txn_nexus_op_begin(i2c_txn_t *);
475 extern void i2c_txn_nexus_op_end(i2c_txn_t *);
476 extern void i2c_txn_ctrl_unlock(i2c_txn_t *);
477 extern void i2c_txn_free(i2c_txn_t *);
478 
479 /*
480  * I/O operations. These require the controller lock.
481  */
482 extern bool i2c_ctrl_io_smbus(i2c_txn_t *, i2c_ctrl_t *, i2c_port_t *,
483     smbus_req_t *);
484 extern bool i2c_ctrl_io_i2c(i2c_txn_t *, i2c_ctrl_t *, i2c_port_t *,
485     i2c_req_t *);
486 
487 /*
488  * Mux related functions.
489  */
490 extern bool i2c_mux_update(i2c_txn_t *, i2c_ctrl_t *, i2c_port_t *,
491     i2c_error_t *);
492 extern void i2c_mux_remove_port(i2c_txn_t *, i2c_ctrl_t *, i2c_port_t *);
493 
494 /*
495  * Address allocations.
496  */
497 extern bool i2c_addr_alloc(i2c_port_t *, const i2c_addr_t *,
498     i2c_error_t *);
499 extern void i2c_addr_free(i2c_port_t *, const i2c_addr_t *);
500 extern bool i2c_addr_alloc_shared(i2c_port_t *, const i2c_addr_t *,
501     major_t, i2c_error_t *);
502 extern void i2c_addr_free_shared(i2c_port_t *, const i2c_addr_t *,
503     major_t);
504 extern void i2c_addr_info_7b(const i2c_port_t *, ui2c_port_info_t *);
505 
506 /*
507  * Device related functions.
508  */
509 extern i2c_dev_t *i2c_device_find_by_addr(i2c_txn_t *, i2c_port_t *,
510     const i2c_addr_t *);
511 extern i2c_dev_t *i2c_device_init(i2c_txn_t *, i2c_port_t *, const i2c_addr_t *,
512     const char *, char *const *, uint_t, i2c_error_t *);
513 extern bool i2c_device_config(i2c_port_t *, i2c_dev_t *);
514 extern bool i2c_device_unconfig(i2c_port_t *, i2c_dev_t *);
515 extern void i2c_device_fini(i2c_txn_t *, i2c_port_t *, i2c_dev_t *);
516 
517 /*
518  * Misc. client related functions that are shared.
519  */
520 extern bool i2c_dip_is_dev(dev_info_t *);
521 extern i2c_nexus_t *i2c_dev_to_nexus(dev_info_t *);
522 
523 /*
524  * Validation functions shared across user / client requests.
525  */
526 extern bool i2c_addr_validate(const i2c_addr_t *, i2c_error_t *);
527 
528 /*
529  * Iterate over all parent ports that are above this entry. Note, there may be
530  * none and therefore the function may not be called. The callback will not be
531  * called for the starting port.
532  */
533 typedef bool (*i2c_port_f)(i2c_port_t *, void *);
534 extern void i2c_port_parent_iter(i2c_port_t *, i2c_port_f, void *);
535 extern void i2c_port_iter(i2c_port_t *, i2c_port_f, void *);
536 
537 /*
538  * Property Interfaces.
539  */
540 extern uint16_t i2c_prop_nstd();
541 extern const char *i2c_prop_name(i2c_prop_t);
542 extern bool i2c_prop_info(i2c_ctrl_t *, ui2c_prop_info_t *);
543 extern bool i2c_prop_get(i2c_ctrl_t *, i2c_prop_t, void *, uint32_t *,
544     i2c_error_t *);
545 extern bool i2c_prop_set(i2c_txn_t *, i2c_ctrl_t *, i2c_prop_t, const void *,
546     uint32_t, i2c_error_t *);
547 
548 #ifdef __cplusplus
549 }
550 #endif
551 
552 #endif /* _I2CNEX_H */
553