xref: /illumos-gate/usr/src/lib/libi2c/common/libi2c_impl.h (revision 32002227574cf0a435dc03de622191ca53724f0a)
1*32002227SRobert Mustacchi /*
2*32002227SRobert Mustacchi  * This file and its contents are supplied under the terms of the
3*32002227SRobert Mustacchi  * Common Development and Distribution License ("CDDL"), version 1.0.
4*32002227SRobert Mustacchi  * You may only use this file in accordance with the terms of version
5*32002227SRobert Mustacchi  * 1.0 of the CDDL.
6*32002227SRobert Mustacchi  *
7*32002227SRobert Mustacchi  * A full copy of the text of the CDDL should have accompanied this
8*32002227SRobert Mustacchi  * source.  A copy of the CDDL is also available via the Internet at
9*32002227SRobert Mustacchi  * http://www.illumos.org/license/CDDL.
10*32002227SRobert Mustacchi  */
11*32002227SRobert Mustacchi 
12*32002227SRobert Mustacchi /*
13*32002227SRobert Mustacchi  * Copyright 2025 Oxide Computer Company
14*32002227SRobert Mustacchi  */
15*32002227SRobert Mustacchi 
16*32002227SRobert Mustacchi #ifndef _LIBI2C_IMPL_H
17*32002227SRobert Mustacchi #define	_LIBI2C_IMPL_H
18*32002227SRobert Mustacchi 
19*32002227SRobert Mustacchi /*
20*32002227SRobert Mustacchi  * Implementation details of libi2c.
21*32002227SRobert Mustacchi  */
22*32002227SRobert Mustacchi 
23*32002227SRobert Mustacchi #include <locale.h>
24*32002227SRobert Mustacchi #include <libnvpair.h>
25*32002227SRobert Mustacchi #include <libi2c.h>
26*32002227SRobert Mustacchi #include <sys/i2c/ioctl.h>
27*32002227SRobert Mustacchi 
28*32002227SRobert Mustacchi #ifdef __cplusplus
29*32002227SRobert Mustacchi extern "C" {
30*32002227SRobert Mustacchi #endif
31*32002227SRobert Mustacchi 
32*32002227SRobert Mustacchi /*
33*32002227SRobert Mustacchi  * Maximum size of an internal error message.
34*32002227SRobert Mustacchi  */
35*32002227SRobert Mustacchi #define	I2C_ERR_LEN	1024
36*32002227SRobert Mustacchi 
37*32002227SRobert Mustacchi /*
38*32002227SRobert Mustacchi  * Name of the driver that we expect to be driving an instance of the i2c nexus.
39*32002227SRobert Mustacchi  */
40*32002227SRobert Mustacchi #define	I2C_NEX_DRV	"i2cnex"
41*32002227SRobert Mustacchi 
42*32002227SRobert Mustacchi typedef struct i2c_err_data {
43*32002227SRobert Mustacchi 	i2c_err_t ie_err;
44*32002227SRobert Mustacchi 	int32_t ie_syserr;
45*32002227SRobert Mustacchi 	i2c_ctrl_error_t ie_ctrl_err;
46*32002227SRobert Mustacchi 	char ie_errmsg[I2C_ERR_LEN];
47*32002227SRobert Mustacchi 	size_t ie_errlen;
48*32002227SRobert Mustacchi } i2c_err_data_t;
49*32002227SRobert Mustacchi 
50*32002227SRobert Mustacchi struct i2c_hdl {
51*32002227SRobert Mustacchi 	i2c_err_data_t ih_err;
52*32002227SRobert Mustacchi 	locale_t ih_c_loc;
53*32002227SRobert Mustacchi 	int ih_devfd;
54*32002227SRobert Mustacchi };
55*32002227SRobert Mustacchi 
56*32002227SRobert Mustacchi struct i2c_ctrl_disc {
57*32002227SRobert Mustacchi 	di_node_t icd_devi;
58*32002227SRobert Mustacchi 	di_minor_t icd_minor;
59*32002227SRobert Mustacchi };
60*32002227SRobert Mustacchi 
61*32002227SRobert Mustacchi struct i2c_ctrl_iter {
62*32002227SRobert Mustacchi 	i2c_hdl_t *ci_hdl;
63*32002227SRobert Mustacchi 	di_node_t ci_root;
64*32002227SRobert Mustacchi 	bool ci_done;
65*32002227SRobert Mustacchi 	di_node_t ci_cur;
66*32002227SRobert Mustacchi 	i2c_ctrl_disc_t ci_disc;
67*32002227SRobert Mustacchi };
68*32002227SRobert Mustacchi 
69*32002227SRobert Mustacchi struct i2c_ctrl {
70*32002227SRobert Mustacchi 	i2c_hdl_t *ctrl_hdl;
71*32002227SRobert Mustacchi 	int32_t ctrl_inst;
72*32002227SRobert Mustacchi 	char *ctrl_name;
73*32002227SRobert Mustacchi 	char *ctrl_path;
74*32002227SRobert Mustacchi 	char *ctrl_minor;
75*32002227SRobert Mustacchi 	uint16_t ctrl_nstd;
76*32002227SRobert Mustacchi 	uint16_t ctrl_npriv;
77*32002227SRobert Mustacchi 	int ctrl_fd;
78*32002227SRobert Mustacchi };
79*32002227SRobert Mustacchi 
80*32002227SRobert Mustacchi struct i2c_port_disc {
81*32002227SRobert Mustacchi 	di_node_t pd_devi;
82*32002227SRobert Mustacchi 	char pd_path[PATH_MAX];
83*32002227SRobert Mustacchi };
84*32002227SRobert Mustacchi 
85*32002227SRobert Mustacchi struct i2c_port_iter {
86*32002227SRobert Mustacchi 	i2c_hdl_t *pi_hdl;
87*32002227SRobert Mustacchi 	bool pi_done;
88*32002227SRobert Mustacchi 	di_node_t pi_root;
89*32002227SRobert Mustacchi 	uint32_t pi_nalloc;
90*32002227SRobert Mustacchi 	uint32_t pi_nports;
91*32002227SRobert Mustacchi 	uint32_t pi_curport;
92*32002227SRobert Mustacchi 	di_node_t *pi_ports;
93*32002227SRobert Mustacchi 	i2c_port_disc_t pi_disc;
94*32002227SRobert Mustacchi };
95*32002227SRobert Mustacchi 
96*32002227SRobert Mustacchi struct i2c_port {
97*32002227SRobert Mustacchi 	i2c_hdl_t *port_hdl;
98*32002227SRobert Mustacchi 	int32_t port_inst;
99*32002227SRobert Mustacchi 	int port_fd;
100*32002227SRobert Mustacchi 	char *port_name;
101*32002227SRobert Mustacchi 	char *port_minor;
102*32002227SRobert Mustacchi 	char port_path[PATH_MAX];
103*32002227SRobert Mustacchi 	ui2c_port_info_t port_info;
104*32002227SRobert Mustacchi 	i2c_port_type_t port_type;
105*32002227SRobert Mustacchi };
106*32002227SRobert Mustacchi 
107*32002227SRobert Mustacchi struct i2c_port_map {
108*32002227SRobert Mustacchi 	i2c_hdl_t *pm_hdl;
109*32002227SRobert Mustacchi 	ui2c_port_info_t pm_info;
110*32002227SRobert Mustacchi };
111*32002227SRobert Mustacchi 
112*32002227SRobert Mustacchi struct i2c_io_req {
113*32002227SRobert Mustacchi 	i2c_port_t *io_port;
114*32002227SRobert Mustacchi 	bool io_addr_valid;
115*32002227SRobert Mustacchi 	i2c_addr_t io_addr;
116*32002227SRobert Mustacchi 	size_t io_tx_len;
117*32002227SRobert Mustacchi 	size_t io_rx_len;
118*32002227SRobert Mustacchi 	const void *io_tx_buf;
119*32002227SRobert Mustacchi 	void *io_rx_buf;
120*32002227SRobert Mustacchi };
121*32002227SRobert Mustacchi 
122*32002227SRobert Mustacchi struct smbus_io_req {
123*32002227SRobert Mustacchi 	i2c_port_t *sir_port;
124*32002227SRobert Mustacchi 	bool sir_addr_valid;
125*32002227SRobert Mustacchi 	i2c_addr_t sir_addr;
126*32002227SRobert Mustacchi 	bool sir_op_valid;
127*32002227SRobert Mustacchi 	smbus_op_t sir_op;
128*32002227SRobert Mustacchi 	i2c_req_flags_t sir_flags;
129*32002227SRobert Mustacchi 	uint8_t sir_cmd;
130*32002227SRobert Mustacchi 	uint64_t sir_write;
131*32002227SRobert Mustacchi 	const void *sir_writep;
132*32002227SRobert Mustacchi 	size_t sir_wlen;
133*32002227SRobert Mustacchi 	void *sir_readp;
134*32002227SRobert Mustacchi 	size_t sir_rlen;
135*32002227SRobert Mustacchi };
136*32002227SRobert Mustacchi 
137*32002227SRobert Mustacchi typedef enum {
138*32002227SRobert Mustacchi 	I2C_DEV_ADD_REQ_FIELD_NAME	= 1 << 0,
139*32002227SRobert Mustacchi 	I2C_DEV_ADD_REQ_FIELD_ADDR	= 1 << 1
140*32002227SRobert Mustacchi } i2c_dev_add_req_field_t;
141*32002227SRobert Mustacchi 
142*32002227SRobert Mustacchi struct i2c_dev_add_req {
143*32002227SRobert Mustacchi 	i2c_port_t *add_port;
144*32002227SRobert Mustacchi 	nvlist_t *add_nvl;
145*32002227SRobert Mustacchi 	uint32_t add_need;
146*32002227SRobert Mustacchi };
147*32002227SRobert Mustacchi 
148*32002227SRobert Mustacchi typedef struct {
149*32002227SRobert Mustacchi 	di_minor_t dmi_minor;
150*32002227SRobert Mustacchi 	di_node_t dmi_node;
151*32002227SRobert Mustacchi } dev_map_info_t;
152*32002227SRobert Mustacchi 
153*32002227SRobert Mustacchi typedef struct {
154*32002227SRobert Mustacchi 	di_node_t dpi_port;
155*32002227SRobert Mustacchi 	bool dpi_scanned;
156*32002227SRobert Mustacchi 	bool dpi_7bit_done;
157*32002227SRobert Mustacchi 	bool dpi_10bit_done;
158*32002227SRobert Mustacchi 	uint16_t dpi_curidx;
159*32002227SRobert Mustacchi 	dev_map_info_t dpi_7b[1 << 7];
160*32002227SRobert Mustacchi 	dev_map_info_t dpi_10b[1 << 10];
161*32002227SRobert Mustacchi } dev_port_info_t;
162*32002227SRobert Mustacchi 
163*32002227SRobert Mustacchi struct i2c_dev_disc {
164*32002227SRobert Mustacchi 	const dev_map_info_t *idd_map;
165*32002227SRobert Mustacchi 	const dev_port_info_t *idd_port;
166*32002227SRobert Mustacchi 	char idd_path[PATH_MAX];
167*32002227SRobert Mustacchi };
168*32002227SRobert Mustacchi 
169*32002227SRobert Mustacchi struct i2c_dev_iter {
170*32002227SRobert Mustacchi 	i2c_hdl_t *di_hdl;
171*32002227SRobert Mustacchi 	bool di_done;
172*32002227SRobert Mustacchi 	i2c_port_iter_t *di_iter;
173*32002227SRobert Mustacchi 	const i2c_port_disc_t *di_curport;
174*32002227SRobert Mustacchi 	dev_port_info_t di_info;
175*32002227SRobert Mustacchi 	i2c_dev_disc_t di_disc;
176*32002227SRobert Mustacchi };
177*32002227SRobert Mustacchi 
178*32002227SRobert Mustacchi struct i2c_dev_info {
179*32002227SRobert Mustacchi 	char *dinfo_name;
180*32002227SRobert Mustacchi 	char dinfo_path[PATH_MAX];
181*32002227SRobert Mustacchi 	char *dinfo_driver;
182*32002227SRobert Mustacchi 	char *dinfo_minor;
183*32002227SRobert Mustacchi 	int dinfo_inst;
184*32002227SRobert Mustacchi 	uint32_t dinfo_naddrs;
185*32002227SRobert Mustacchi 	i2c_addr_t *dinfo_addrs;
186*32002227SRobert Mustacchi 	ui2c_dev_info_t dinfo_info;
187*32002227SRobert Mustacchi };
188*32002227SRobert Mustacchi 
189*32002227SRobert Mustacchi struct i2c_prop_info {
190*32002227SRobert Mustacchi 	i2c_hdl_t *pinfo_hdl;
191*32002227SRobert Mustacchi 	ui2c_prop_info_t pinfo_info;
192*32002227SRobert Mustacchi 	bool pinfo_sup;
193*32002227SRobert Mustacchi };
194*32002227SRobert Mustacchi 
195*32002227SRobert Mustacchi struct i2c_mux_disc {
196*32002227SRobert Mustacchi 	di_node_t md_devi;
197*32002227SRobert Mustacchi 	di_minor_t md_minor;
198*32002227SRobert Mustacchi 	char md_path[PATH_MAX];
199*32002227SRobert Mustacchi 	ui2c_mux_info_t md_info;
200*32002227SRobert Mustacchi };
201*32002227SRobert Mustacchi 
202*32002227SRobert Mustacchi struct i2c_mux_iter {
203*32002227SRobert Mustacchi 	i2c_hdl_t *mi_hdl;
204*32002227SRobert Mustacchi 	di_node_t mi_root;
205*32002227SRobert Mustacchi 	di_node_t mi_cur;
206*32002227SRobert Mustacchi 	bool mi_done;
207*32002227SRobert Mustacchi 	i2c_mux_disc_t mi_disc;
208*32002227SRobert Mustacchi };
209*32002227SRobert Mustacchi 
210*32002227SRobert Mustacchi /*
211*32002227SRobert Mustacchi  * Common success and failure interfaces.
212*32002227SRobert Mustacchi  */
213*32002227SRobert Mustacchi extern bool i2c_error(i2c_hdl_t *, i2c_err_t, int32_t, const char *, ...)
214*32002227SRobert Mustacchi     __PRINTFLIKE(4);
215*32002227SRobert Mustacchi extern bool i2c_success(i2c_hdl_t *);
216*32002227SRobert Mustacchi extern bool i2c_ioctl_syserror(i2c_hdl_t *, int, const char *);
217*32002227SRobert Mustacchi extern bool i2c_ioctl_error(i2c_hdl_t *, const i2c_error_t *, const char *);
218*32002227SRobert Mustacchi extern bool i2c_nvlist_error(i2c_hdl_t *, int, const char *);
219*32002227SRobert Mustacchi 
220*32002227SRobert Mustacchi /*
221*32002227SRobert Mustacchi  * Common validation routines
222*32002227SRobert Mustacchi  */
223*32002227SRobert Mustacchi extern bool i2c_addr_validate(i2c_hdl_t *, const i2c_addr_t *);
224*32002227SRobert Mustacchi extern bool i2c_name_validate(i2c_hdl_t *, const char *, const char *);
225*32002227SRobert Mustacchi 
226*32002227SRobert Mustacchi /*
227*32002227SRobert Mustacchi  * Misc. routines.
228*32002227SRobert Mustacchi  */
229*32002227SRobert Mustacchi typedef enum {
230*32002227SRobert Mustacchi 	I2C_NODE_T_CTRL,
231*32002227SRobert Mustacchi 	I2C_NODE_T_PORT,
232*32002227SRobert Mustacchi 	I2C_NODE_T_DEV,
233*32002227SRobert Mustacchi 	I2C_NODE_T_MUX,
234*32002227SRobert Mustacchi 	I2C_NODE_T_OTHER
235*32002227SRobert Mustacchi } i2c_node_type_t;
236*32002227SRobert Mustacchi 
237*32002227SRobert Mustacchi extern i2c_node_type_t i2c_node_type(di_node_t);
238*32002227SRobert Mustacchi extern di_minor_t i2c_node_minor(di_node_t);
239*32002227SRobert Mustacchi extern bool i2c_node_is_type(di_node_t, i2c_node_type_t);
240*32002227SRobert Mustacchi extern bool i2c_node_to_path(i2c_hdl_t *, di_node_t, char *, size_t);
241*32002227SRobert Mustacchi extern bool i2c_kernel_address_parse(i2c_hdl_t *, const char *, i2c_addr_t *);
242*32002227SRobert Mustacchi extern bool i2c_reg_to_addr(i2c_hdl_t *, di_node_t, i2c_addr_t *, uint32_t);
243*32002227SRobert Mustacchi extern bool i2c_addr_equal(const i2c_addr_t *, const i2c_addr_t *);
244*32002227SRobert Mustacchi 
245*32002227SRobert Mustacchi /*
246*32002227SRobert Mustacchi  * Various path lookup routines.
247*32002227SRobert Mustacchi  */
248*32002227SRobert Mustacchi extern di_node_t i2c_path_find_ctrl(di_node_t, const char *);
249*32002227SRobert Mustacchi extern di_node_t i2c_path_find_mux(di_node_t);
250*32002227SRobert Mustacchi extern di_node_t i2c_path_find_port(di_node_t, const char *);
251*32002227SRobert Mustacchi extern di_node_t i2c_path_find_device(i2c_hdl_t *, di_node_t, const char *);
252*32002227SRobert Mustacchi extern bool i2c_path_parse(i2c_hdl_t *, const char *, di_node_t, di_node_t *,
253*32002227SRobert Mustacchi     i2c_node_type_t *, i2c_err_t);
254*32002227SRobert Mustacchi 
255*32002227SRobert Mustacchi #ifdef __cplusplus
256*32002227SRobert Mustacchi }
257*32002227SRobert Mustacchi #endif
258*32002227SRobert Mustacchi 
259*32002227SRobert Mustacchi #endif /* _LIBI2C_IMPL_H */
260