STRUCT I3C_MASTER_CONTROLLER_OPS(9)

πŸ“¦ version 7.3.1, in nixpkgs unstable

πŸ’– NAME πŸ’–

struct i3c_master_controller_ops β€” the I3C master methods, aka the vibe check your controller has to pass πŸ’…


✨ SYNOPSIS ✨

okay bestie, here's the whole squad roster, copied exactly, no cap:

struct i3c_master_controller_ops {
    int (*bus_init)(struct i3c_master_controller *master);
    void (*bus_cleanup)(struct i3c_master_controller *master);
    int (*attach_i3c_dev)(struct i3c_dev_desc *dev);
    int (*reattach_i3c_dev)(struct i3c_dev_desc *dev, u8 old_dyn_addr);
    void (*detach_i3c_dev)(struct i3c_dev_desc *dev);
    int (*do_daa)(struct i3c_master_controller *master);
    bool (*supports_ccc_cmd)(struct i3c_master_controller *master, const
struct i3c_ccc_cmd *cmd);
    int (*send_ccc_cmd)(struct i3c_master_controller *master, struct
i3c_ccc_cmd *cmd);
    int (*i3c_xfers)(struct i3c_dev_desc *dev, struct i3c_xfer *xfers,
int nxfers, enum i3c_xfer_mode mode);
    int (*attach_i2c_dev)(struct i2c_dev_desc *dev);
    void (*detach_i2c_dev)(struct i2c_dev_desc *dev);
    int (*i2c_xfers)(struct i2c_dev_desc *dev, struct i2c_msg *xfers,
int nxfers);
    int (*request_ibi)(struct i3c_dev_desc *dev, const struct
i3c_ibi_setup *req);
    void (*free_ibi)(struct i3c_dev_desc *dev);
    int (*enable_ibi)(struct i3c_dev_desc *dev);
    int (*disable_ibi)(struct i3c_dev_desc *dev);
    void (*recycle_ibi_slot)(struct i3c_dev_desc *dev, struct
i3c_ibi_slot *slot);
    int (*enable_hotjoin)(struct i3c_master_controller *master);
    int (*disable_hotjoin)(struct i3c_master_controller *master);
    int (*set_speed)(struct i3c_master_controller *master, enum
i3c_open_drain_speed speed);
    int (*set_dev_nack_retry)(struct i3c_master_controller *master,
unsigned int dev_nack_retry_cnt);
 };

🌸 Members 🌸

buckle up, we're going through all twenty-one of these bad boys one by one 🫢

  • bus_init β€” the hook that's literally responsible for initializing the I3C bus. You should at least call master_set_info from in there and set the bus mode. Controller-specific init? yeah, you can absolutely drop that in here too. This method is mandatory. πŸ”₯
  • bus_cleanup β€” undoes everything you did in i3c_master_controller_ops->bus_init. This method is optional.
  • attach_i3c_dev β€” called every single time an I3C device attaches to the bus. could be after a DAA, or when a device is statically declared by the FW, in which case it'll only have a static address and the dynamic address will be 0. heads up: when this function gets called, device information have not been retrieved yet πŸ‘€. this is a great spot to attach master-controller-specific data to I3C devices. This method is optional.
  • reattach_i3c_dev β€” called every time an I3C device has its addressed changed. could be because the device got powered down and lost its address, or because a device had a static address and got assigned a dynamic address with SETDASA. This method is optional.
  • detach_i3c_dev β€” called when an I3C device detaches from the bus. usually this happens when the master device is unregistered. This method is optional.
  • do_daa β€” do a DAA (Dynamic Address Assignment) procedure. this procedure should send an ENTDAA CCC command and then add all devices discovered sure the DAA using i3c_master_add_i3c_dev_locked. devices added with i3c_master_add_i3c_dev_locked will then be attached or re-attached to the controller. This method is mandatory. πŸ‘‘
  • supports_ccc_cmd β€” should return true if the CCC command is supported, false otherwise. This method is optional β€” if you don't provide it, the core just assumes all CCC commands are supported. optimistic queen ✨
  • send_ccc_cmd β€” send a CCC command. This method is mandatory.
  • i3c_xfers β€” do one or several I3C SDR or HDR transfers. This method is mandatory.
  • attach_i2c_dev β€” called every time an I2C device attaches to the bus. great place to attach master-controller-specific data to I2C devices. This method is optional.
  • detach_i2c_dev β€” called when an I2C device detaches from the bus. usually happens when the master device is unregistered. This method is optional.
  • i2c_xfers β€” do one or several I2C transfers. ⚠️ note that, unlike i3c transfers, the core does not guarantee that buffers attached to the transfers are DMA-safe. if drivers want DMA-safe buffers, they should use the i2c_get_dma_safe_msg_buf and i2c_put_dma_safe_msg_buf helpers provided by the I2C framework. This method is mandatory.
  • request_ibi β€” attach an IBI handler to an I3C device. this implies defining an IBI handler and the constraints of the IBI (maximum payload length and number of pre-allocated slots). some controllers support less IBI-capable devices than regular devices, so this method might return -EBUSY if there's no more space for an extra IBI registration. This method is optional.
  • free_ibi β€” free an IBI previously requested with ->request_ibi. the IBI should have been disabled with ->disable_irq prior to that. This method is mandatory only if ->request_ibi is not NULL.
  • enable_ibi β€” enable the IBI. only valid if ->request_ibi has been called prior to ->enable_ibi. the controller should first enable the IBI on the controller end (for example, unmask the hardware IRQ) and then send the ENEC CCC command (with the IBI flag set) to the I3C device. This method is mandatory only if ->request_ibi is not NULL.
  • disable_ibi β€” disable an IBI. first send the DISEC CCC command with the IBI flag set, and then deactivate the hardware IRQ on the controller end. This method is mandatory only if ->request_ibi is not NULL.
  • recycle_ibi_slot β€” recycle an IBI slot. called every time an IBI has been processed by its handler. the IBI slot should be put back in the IBI slot pool so the controller can re-use it for a future IBI. This method is mandatory only if ->request_ibi is not NULL.
  • enable_hotjoin β€” enable hot join event detect. πŸ¦‹
  • disable_hotjoin β€” disable hot join event detect. πŸ™ˆ
  • set_speed β€” adjust I3C open drain mode timing.
  • set_dev_nack_retry β€” configure device NACK retry count for the master controller.

πŸŽ€ SEE ALSO πŸŽ€

Kernel file ./include/linux/i3c/master.h, plus the whole friend group:

struct i3c_i2c_dev_desc(9), struct i2c_dev_boardinfo(9), struct i2c_dev_desc(9), struct i3c_ibi_slot(9), struct i3c_device_ibi_info(9), struct i3c_dev_boardinfo(9), struct i3c_dev_desc(9), struct i3c_device(9), enum i3c_bus_mode(9), enum i3c_open_drain_speed(9), enum i3c_addr_slot_status(9), struct i3c_bus(9), struct i3c_master_controller(9), i3c_bus_for_each_i2cdev(9), i3c_bus_for_each_i3cdev(9), struct i3c_dma(9), i3c_dev_get_master_data(9), i3c_dev_set_master_data(9), i2c_dev_get_master_data(9), i2c_dev_set_master_data(9), i3c_dev_get_master(9), i2c_dev_get_master(9), i3c_master_get_bus(9)


that's the whole page bestie, go forth and init your bus πŸ’œ

kisses from <pink>./include/linux/i3c</pink>, dated October 2026 β€” struct i3c_m...ntroller_ops(9), and yes the title got truncated by the renderer, not me, that's just how it ate it 😭 periodt πŸŽ€

πŸ“¦ where this page comes from