/* * This file and its contents are supplied under the terms of the * Common Development and Distribution License ("CDDL"), version 1.0. * You may only use this file in accordance with the terms of version * 1.0 of the CDDL. * * A full copy of the text of the CDDL should have accompanied this * source. A copy of the CDDL is also available via the Internet at * http://www.illumos.org/license/CDDL. */ /* * Copyright 2025 Oxide Computer Company */ #ifndef _SYS_I2C_I2C_H #define _SYS_I2C_I2C_H /* * General i2c definitions that should be shared between both userland and the * kernel. Kernel device drivers include <sys/i2c/controller.h>, * <sys/i2c/mux.h>, or <sys/i2c/client.h> depending on the type of device they * are. Userland should generally use <libi2c.h> or <sys/i2c/ui2c.h> if it's the * implementation of libi2c. */ #include <sys/stdint.h> #include <sys/stdbool.h> #ifdef __cplusplus extern "C" { #endif /* * Different allowed values for I2C and SMBus speeds. In the future, we'll * determine how I3C based options like different supported clock rates and * SDR/DDR fit in here. */ typedef enum { /* * 100 kHz Standard operation. */ I2C_SPEED_STD = 1 << 0, /* * 400 kHz Fast-mode operation. */ I2C_SPEED_FAST = 1 << 1, /* * 1000 MHz Fast-mode plus operation. */ I2C_SPEED_FPLUS = 1 << 2, /* * 3400 MHz High-speed mode operation. */ I2C_SPEED_HIGH = 1 << 3, /* * 5000 MHz Ultra-Fast mode operation. */ I2C_SPEED_ULTRA = 1 << 4 } i2c_speed_t; /* * Different types of controllers. */ typedef enum { I2C_CTRL_TYPE_I2C = 1, I2C_CTRL_TYPE_I3C, I2C_CTRL_TYPE_SMBUS } i2c_ctrl_type_t; /* * This represents the series of errors that can be generated by the various I2C * APIs. These are grouped into several different units that cover behavior * specific to the core (impacting everything) to properties, user-specific * behavior, kernel driver clients, etc. */ typedef enum { I2C_CORE_E_OK = 0, /* * Indicates that the controller I/O failed. The reason is specified in * the controller error. */ I2C_CORE_E_CONTROLLER, /* * The following pair indicate that a given address class or value for * an address within a valid address class are wrong. */ I2C_CORE_E_BAD_ADDR_TYPE, I2C_CORE_E_BAD_ADDR, /* * This indicates that the requested address type, while valid, is not * supported. For example, trying to send to a 10-bit address on a * controller that does not support it. */ I2C_CORE_E_UNSUP_ADDR_TYPE, /* * Indicates that the address in question is reserved by a corresponding * specification. */ I2C_CORE_E_ADDR_RSVD, /* * Indicates that the address in question is already in use and * therefore cannot be used. */ I2C_CORE_E_ADDR_IN_USE, /* * Indicates that the address could be used, but it has exceeded the * per-address usage count. This usually represents a place where the * kernel can be improved. */ I2C_CORE_E_ADDR_REFCNT, /* * Indicates that there is no device with the specified address. */ I2C_CORE_E_UNKNOWN_ADDR, /* * Indicates that the request type can't be translated to something the * underlying controller actually supports. For example, this would * cover trying to translate certain kinds of I2C requests to an SMBus * controller that supports limited types of operations or vice versa. */ I2C_CORE_E_CANT_XLATE_REQ, /* * This indicates that a request had neither a read nor a write and * therefore cannot continue. This constraint on I/O may be lifted in * the future. */ I2C_CORE_E_NEED_READ_OR_WRITE, /* * These indicate that invalid flags values, an invalid read length, or * invalid write length was encountered. */ I2C_CORE_E_BAD_I2C_REQ_FLAGS, I2C_CORE_E_BAD_I2C_REQ_READ_LEN, I2C_CORE_E_BAD_I2C_REQ_WRITE_LEN, /* * These indicate similar situations in the SMBus request field. */ I2C_CORE_E_BAD_SMBUS_REQ_FLAGS, I2C_CORE_E_BAD_SMBUS_READ_LEN, I2C_CORE_E_BAD_SMBUS_WRITE_LEN, I2C_CORE_E_BAD_SMBUS_OP, /* * Indicates that the controller does not support the requested SMBus * operation. */ I2C_CORE_E_UNSUP_SMBUS_OP, /* * Indicates that the controller is already owned by someone and the * caller asked not to block. */ I2C_CORE_E_LOCK_WOULD_BLOCK, /* * Indicates that the caller took a signal while waiting to acquire the * controller. */ I2C_CORE_E_LOCK_WAIT_SIGNAL, /* * Indicates that a passed in nvlist was larger than the maximum value. */ I2C_IOCTL_E_NVL_TOO_BIG = 0x1000, /* * Indicates that the nvlist was not parseable. */ I2C_IOCTL_E_NVL_INVALID, /* * Indicates that the nvlist contained missing keys, keys that we don't * know how to handle, and keys that are the wrong type. If this gets * much more complex, the interface should change to the kgpio error * style where there is an additional nvlist there. */ I2C_IOCTL_E_NVL_KEY_MISSING, I2C_IOCTL_E_NVL_KEY_UNKNOWN, I2C_IOCTL_E_NVL_KEY_BAD_TYPE, /* * Indicates that a pointer to user data inside of an ioctl (not the * overall ioctl itself) was not valid and generated a fault. */ I2C_IOCTL_E_BAD_USER_DATA, /* * Indicates that there was no kernel memory available for the request. */ I2C_IOCTL_E_NO_KERN_MEM, /* * Indicates that a string that is being used for a device name or * compatible array contains illegal characters or is too long. */ I2C_IOCTL_E_BAD_DEV_NAME, /* * Indicates that the length of the compatible range is longer than the * system will allow to be set. */ I2C_IOCTL_E_COMPAT_LEN_RANGE, /* * Indicates that something went wrong with trying to deal with nexus * related operations on a child. */ I2C_IOCTL_E_NEXUS, /* * Indicates that a nexus operations was attempted while trying to hold * a bus lock. */ I2C_IOCTL_E_NO_BUS_LOCK_NEXUS, /* * Indicates that an ioctl operation could not be started because the * client in question already has one in flight that requires the * controller lock. */ I2C_IOCTL_E_IN_PROGRESS, /* * Indicates that the passed dev_info_t does not correspond to an i2c * device. */ I2C_CLIENT_E_BAD_DIP = 0x2000, /* * Indicates that the regs[] index is invalid for the device. */ I2C_CLIENT_E_BAD_REG_IDX, /* * Indicates that the specific set of flags are invalid. */ I2C_CLIENT_E_BAD_CLAIM_FLAGS, I2C_CLIENT_E_BAD_IO_FLAGS, I2C_CLIENT_E_BAD_LOCK_FLAGS, /* * Indicates that the caller was interrupted while trying to get access * to the client for I/O. */ I2C_CLIENT_E_SIGNAL, /* * Thee indicate that there are invalid values in the various register * access attributes. */ I2C_CLIENT_E_BAD_REG_ATTR_VERS, I2C_CLIENT_E_BAD_REG_ATTR_FLAGS, I2C_CLIENT_E_BAD_REG_ATTR_RLEN, I2C_CLIENT_E_BAD_REG_ATTR_ALEN, I2C_CLIENT_E_BAD_REG_ATTR_ENDIAN, I2C_CLIENT_E_BAD_REG_ATTR_MAX, /* * Indicates that while the register attributes are supported, the * underlying hardware cannot support them. */ I2C_CLIENT_E_REG_ALEN_UNSUP_BY_CTRL, /* * These indicate that I2C register operations were passed invalid * values or that these values would lead to an overflow. */ I2C_CLIENT_E_BAD_REG_ADDR, I2C_CLIENT_E_BAD_REG_COUNT, I2C_CLIENT_E_REG_ADDR_OVERFLOW, I2C_CLIENT_E_REG_IO_TOO_LARGE, /* * Indicates that the size in bytes is a partial number of registers. */ I2C_CLIENT_E_PARTIAL_REG, /* * Indicates that the client has tried to claim a shared address, but * they actually own the address directly. */ I2C_CLIENT_E_CLAIM_OWNED_ADDR, /* * These two indicate that the property is unsupported by the device or * a property ID that is unknown by the system. */ I2C_PROP_E_UNSUP = 0x3000, I2C_PROP_E_UNKNOWN, /* * Indicates that the property can't be written to because it is * read-only. */ I2C_PROP_E_READ_ONLY, /* * Indicates that the property buffer is too small. The second indicates * that the property buffer is too large and doesn't make sense for the * property. The latter is only relevant when setting a property. The * former can be triggered in all property interfaces. */ I2C_PROP_E_SMALL_BUF, I2C_PROP_E_TOO_BIG_BUF, /* * Indicates that the property value is invalid. */ I2C_PROP_E_BAD_VAL, /* * Indicates that the controller doesn't support setting properties. */ I2C_PROP_E_SET_UNSUP, /* * Indicates that the mux flag is unknown. */ I2C_MUX_E_BAD_FLAG = 0x4000 } i2c_errno_t; /* * These represent errors that the controller generates and/or detects while * attempting to perform I/O. Some controllers provide relatively rich * diagnostics as to what went wrong. Others, provide only generic classes of * errors. Try to use the most specific error possible. */ typedef enum { I2C_CTRL_E_OK = 0, /* * This is a generic class that represents something happened internal * to the controller. In general, this should be used sparingly and only * for something that only makes semantic sense on a single controller. * This should not be a property of something related to I2C/SMBus/I3C * directly. */ I2C_CTRL_E_INTERNAL, /* * This is a variant of the above that indicates a driver programming * error violated a controller condition. */ I2C_CTRL_E_DRIVER, /* * Indicates that the controller was given a type of command that it * does not support. For example, an SMBus 1.0 controller given an SMBus * 2.0 command. The framework generally is the only tying that will * return this error as drivers should not have to encounter them. */ I2C_CTRL_E_UNSUP_CMD, /* * Indicates that prior to trying to perform the operation, the * controller detected that the bus was busy and after a timeout was * unable to get control of the bus. */ I2C_CTRL_E_BUS_BUSY, /* * This error indicates that there was a no acknowledgement condition. * This should be used both for 7-bit and 10-bit cases. Similarly, for * now this should also be used for cases where no one acknowledges a * general call. */ I2C_CTRL_E_ADDR_NACK, /* * This is a variant on the address NACK. This is used when the address * has been acknowledged, but subsequent data has not been. Some devices * may not be able to make the distinction. If they cannot, use the * catch-all NACK below. */ I2C_CTRL_E_DATA_NACK, /* * This is a case where no NACK occurred, but the controller cannot be * more specific as to where in the process it occurred. */ I2C_CTRL_E_NACK, /* * Indicates that the controller lost arbitration on the bus. A common * cause for this is a data collision. */ I2C_CTRL_E_ARB_LOST, /* * Indicates that a device incorrectly issued an ACK when it was not * expected in the operation. */ I2C_CTRL_E_BAD_ACK, /* * Indicates that the controller failed to successfully finish * transmitting the command within the default request timeout. This * results in the controller aborting the command. Callers cannot assume * anything about the number of bytes that made it out onto the bus. */ I2C_CTRL_E_REQ_TO, /* * Indicates that an SMBus device returned a block read length that * could not be supported by the device or is illegal according to the * specification. For example, a 0 byte length or a length exceeding 32 * bytes for an SMBus 2.0 controller. */ I2C_CTRL_E_BAD_SMBUS_RLEN, /* * Indicates that an SMBus device held the clock low for too long to * effectively trime out the transaction. This is different from the * request timeout as it indicates something the target did. */ I2C_CTRL_E_SMBUS_CLOCK_LOW } i2c_ctrl_error_t; typedef struct { i2c_errno_t i2c_error; i2c_ctrl_error_t i2c_ctrl; } i2c_error_t; /* * General maximum length for an i2c related name, including the NUL. */ #define I2C_NAME_MAX 32 typedef enum i2c_addr_type { I2C_ADDR_7BIT = 0, I2C_ADDR_10BIT } i2c_addr_type_t; /* * This represents the general form of our i2c addresses and what the nexus will * give client devices and drivers in the form of regs[]. */ typedef struct i2c_addr { uint16_t ia_type; uint16_t ia_addr; } i2c_addr_t; /* * This indicates where an address came from. */ typedef enum i2c_addr_source { /* * Indicates that this came from the devices reg[] array. It was either * put there as part of discovering information about the system by the * platform (e.g. ACPI, device tree, etc.) or based on a user's specific * device creation. */ I2C_ADDR_SOURCE_REG = 1, /* * Indicates that the address was one that the driver claimed. */ I2C_ADDR_SOURCE_CLAIMED, /* * Indicates that the address was one that the driver claimed and is * shared across multiple instances. */ I2C_ADDR_SOURCE_SHARED } i2c_addr_source_t; /* * Well-known and other special addresses. I2C reserves several addresses for * special purposes. SMBus has a more extensive of nominal assignments, but * things definitely stomp in that space. */ typedef enum { I2C_RSVD_ADDR_GEN_CALL = 0x00, I2C_RSVD_ADDR_C_BUS = 0x01, I2C_RSVD_ADDR_DIFF_BUS = 0x02, I2C_RSVD_ADDR_FUTURE = 0x03, I2C_RSVD_ADDR_HS_0 = 0x04, I2C_RSVD_ADDR_HS_1 = 0x05, I2C_RSVD_ADDR_HS_2 = 0x06, I2C_RSVD_ADDR_HS_3 = 0x07, I2C_RSVD_ADDR_10B_0 = 0x78, I2C_RSVD_ADDR_10B_1 = 0x79, I2C_RSVD_ADDR_10B_2 = 0x7a, I2C_RSVD_ADDR_10B_3 = 0x7b, I2C_RSVD_ADDR_DID_0 = 0x7c, I2C_RSVD_ADDR_DID_1 = 0x7d, I2C_RSVD_ADDR_DID_2 = 0x7e, I2C_RSVD_ADDR_DID_3 = 0x7f } i2c_rsvd_addr_t; /* * SMBus 2.0 controllers have a maximum byte size of 32 bytes. SMBus 3.0 * increases that to a maximum of 255 bytes. As such we size our maximum request * sizes at 256 bytes in our structures. */ #define SMBUS_V2_MAX_BLOCK 32 #define SMBUS_V3_MAX_BLOCK 255 #define I2C_REQ_MAX 256 typedef enum smbus_op { SMBUS_OP_QUICK_COMMAND, SMBUS_OP_SEND_BYTE, SMBUS_OP_RECV_BYTE, SMBUS_OP_WRITE_BYTE, SMBUS_OP_READ_BYTE, SMBUS_OP_WRITE_WORD, SMBUS_OP_READ_WORD, SMBUS_OP_PROCESS_CALL, SMBUS_OP_WRITE_BLOCK, SMBUS_OP_READ_BLOCK, /* Added in SMBUS 2.0 */ SMBUS_OP_HOST_NOTIFY, SMBUS_OP_BLOCK_PROCESS_CALL, /* Added in SMBUS 3.x */ SMBUS_OP_WRITE_U32, SMBUS_OP_READ_U32, SMBUS_OP_WRITE_U64, SMBUS_OP_READ_U64, /* I2C Compatibility */ SMBUS_OP_I2C_WRITE_BLOCK, SMBUS_OP_I2C_READ_BLOCK } smbus_op_t; typedef enum { /* * Indicates that regardless of whether or not interrupts are supported, * this request should be polled. */ I2C_IO_REQ_F_POLL = 1 << 0, /* * Indicates that this zero-byte I/O quick command is a write. If this * flag is not set then a quick command is a read. */ I2C_IO_REQ_F_QUICK_WRITE = 1 << 1, } i2c_req_flags_t; typedef struct smbus_req { i2c_error_t smbr_error; smbus_op_t smbr_op; i2c_req_flags_t smbr_flags; i2c_addr_t smbr_addr; uint16_t smbr_wlen; uint16_t smbr_rlen; uint8_t smbr_cmd; uint8_t smbr_wdata[I2C_REQ_MAX]; uint8_t smbr_rdata[I2C_REQ_MAX]; } smbus_req_t; typedef struct i2c_req { i2c_error_t ir_error; i2c_req_flags_t ir_flags; i2c_addr_t ir_addr; uint16_t ir_wlen; uint16_t ir_rlen; uint8_t ir_wdata[I2C_REQ_MAX]; uint8_t ir_rdata[I2C_REQ_MAX]; } i2c_req_t; typedef enum i2c_prop_type { /* * A property that is a standard, scalar uint32_t. */ I2C_PROP_TYPE_U32, /* * A property that fits in a uint32_t, but represents a bitfield of * values. */ I2C_PROP_TYPE_BIT32 } i2c_prop_type_t; typedef enum i2c_prop_perm { I2C_PROP_PERM_RO, I2C_PROP_PERM_RW } i2c_prop_perm_t; typedef struct i2c_prop_u32_range { uint32_t ipur_min; uint32_t ipur_max; } i2c_prop_u32_range_t; typedef union i2c_prop_val_range { uint32_t ipvr_bit32; i2c_prop_u32_range_t ipvr_u32; } i2c_prop_val_range_t; typedef struct i2c_prop_range { uint32_t ipr_count; i2c_prop_type_t ipr_type; i2c_prop_val_range_t ipr_range[]; } i2c_prop_range_t; /* * This enumeration contains a list of the properties that are supported. * * In earlier designs we had an initial set of properties for setup and hold * time related aspects, but controllers don't really have a uniform design * here. Some offer different values for RX and TX. Some offer only a single * value. */ typedef enum i2c_prop { /* * This is a uint32_t that is covered by the i2c_speed_t. */ I2C_PROP_BUS_SPEED = 0, /* * This is a uint32_t that indicates the number of ports the device has. */ I2C_PROP_NPORTS, /* * This indicates the controller's type, which is covered by the * i2c_ctrl_type_t. */ I2C_PROP_TYPE, /* * SMBus operations that are supported by the controller. This is a * uint32_t that covers smbus_prop_op_t. */ SMBUS_PROP_SUP_OPS, /* * Maximum sizes that a controller can support for performing different * kinds of I/O. We expect that most I2C controllers will only support a * * single read/write buffer. For SMBus controllers, they should specify * the maximum block size. This covers block reads, writes, and calls. * If a controller supports an I2C mode with a different maximum, then * it can additionally specify the I2c properties. */ I2C_PROP_MAX_READ, I2C_PROP_MAX_WRITE, SMBUS_PROP_MAX_BLOCK, /* * Properties for different timing parameters in I2C devices. These are * all uint32_t values generally in clock cycles. */ I2C_PROP_STD_SCL_HIGH, I2C_PROP_STD_SCL_LOW, I2C_PROP_FAST_SCL_HIGH, I2C_PROP_FAST_SCL_LOW, I2C_PROP_HIGH_SCL_HIGH, I2C_PROP_HIGH_SCL_LOW } i2c_prop_t; typedef enum smbus_prop_op { SMBUS_PROP_OP_QUICK_COMMAND = 1 << SMBUS_OP_QUICK_COMMAND, SMBUS_PROP_OP_SEND_BYTE = 1 << SMBUS_OP_SEND_BYTE, SMBUS_PROP_OP_RECV_BYTE = 1 << SMBUS_OP_RECV_BYTE, SMBUS_PROP_OP_WRITE_BYTE = 1 << SMBUS_OP_WRITE_BYTE, SMBUS_PROP_OP_READ_BYTE = 1 << SMBUS_OP_READ_BYTE, SMBUS_PROP_OP_WRITE_WORD = 1 << SMBUS_OP_WRITE_WORD, SMBUS_PROP_OP_READ_WORD = 1 << SMBUS_OP_READ_WORD, SMBUS_PROP_OP_PROCESS_CALL = 1 << SMBUS_OP_PROCESS_CALL, SMBUS_PROP_OP_WRITE_BLOCK = 1 << SMBUS_OP_WRITE_BLOCK, SMBUS_PROP_OP_READ_BLOCK = 1 << SMBUS_OP_READ_BLOCK, SMBUS_PROP_OP_HOST_NOTIFY = 1 << SMBUS_OP_HOST_NOTIFY, SMBUS_PROP_OP_BLOCK_PROCESS_CALL = 1 << SMBUS_OP_BLOCK_PROCESS_CALL, SMBUS_PROP_OP_WRITE_U32 = 1 << SMBUS_OP_WRITE_U32, SMBUS_PROP_OP_READ_U32 = 1 << SMBUS_OP_READ_U32, SMBUS_PROP_OP_WRITE_U64 = 1 << SMBUS_OP_WRITE_U64, SMBUS_PROP_OP_READ_U64 = 1 << SMBUS_OP_READ_U64, SMBUS_PROP_OP_I2C_WRITE_BLOCK = 1 << SMBUS_OP_I2C_WRITE_BLOCK, SMBUS_PROP_OP_I2C_READ_BLOCK = 1 << SMBUS_OP_I2C_READ_BLOCK } smbus_prop_op_t; /* * The size in bytes of the maximum property name (including the NUL) and the * largest data size. */ #define I2C_PROP_NAME_MAX 32 #define I2C_PROP_SIZE_MAX 256 #ifdef __cplusplus } #endif #endif /* _SYS_I2C_I2C_H */