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