linux/drivers/i3c/master.c

// SPDX-License-Identifier: GPL-2.0
/*
 * Copyright (C) 2018 Cadence Design Systems Inc.
 *
 * Author: Boris Brezillon <[email protected]>
 */

#include <linux/atomic.h>
#include <linux/bug.h>
#include <linux/device.h>
#include <linux/err.h>
#include <linux/export.h>
#include <linux/kernel.h>
#include <linux/list.h>
#include <linux/of.h>
#include <linux/pm_runtime.h>
#include <linux/slab.h>
#include <linux/spinlock.h>
#include <linux/workqueue.h>

#include "internals.h"

static DEFINE_IDR(i3c_bus_idr);
static DEFINE_MUTEX(i3c_core_lock);
static int __i3c_first_dynamic_bus_num;
static BLOCKING_NOTIFIER_HEAD(i3c_bus_notifier);

/**
 * i3c_bus_maintenance_lock - Lock the bus for a maintenance operation
 * @bus: I3C bus to take the lock on
 *
 * This function takes the bus lock so that no other operations can occur on
 * the bus. This is needed for all kind of bus maintenance operation, like
 * - enabling/disabling slave events
 * - re-triggering DAA
 * - changing the dynamic address of a device
 * - relinquishing mastership
 * - ...
 *
 * The reason for this kind of locking is that we don't want drivers and core
 * logic to rely on I3C device information that could be changed behind their
 * back.
 */
static void i3c_bus_maintenance_lock(struct i3c_bus *bus)
{}

/**
 * i3c_bus_maintenance_unlock - Release the bus lock after a maintenance
 *			      operation
 * @bus: I3C bus to release the lock on
 *
 * Should be called when the bus maintenance operation is done. See
 * i3c_bus_maintenance_lock() for more details on what these maintenance
 * operations are.
 */
static void i3c_bus_maintenance_unlock(struct i3c_bus *bus)
{}

/**
 * i3c_bus_normaluse_lock - Lock the bus for a normal operation
 * @bus: I3C bus to take the lock on
 *
 * This function takes the bus lock for any operation that is not a maintenance
 * operation (see i3c_bus_maintenance_lock() for a non-exhaustive list of
 * maintenance operations). Basically all communications with I3C devices are
 * normal operations (HDR, SDR transfers or CCC commands that do not change bus
 * state or I3C dynamic address).
 *
 * Note that this lock is not guaranteeing serialization of normal operations.
 * In other words, transfer requests passed to the I3C master can be submitted
 * in parallel and I3C master drivers have to use their own locking to make
 * sure two different communications are not inter-mixed, or access to the
 * output/input queue is not done while the engine is busy.
 */
void i3c_bus_normaluse_lock(struct i3c_bus *bus)
{}

/**
 * i3c_bus_normaluse_unlock - Release the bus lock after a normal operation
 * @bus: I3C bus to release the lock on
 *
 * Should be called when a normal operation is done. See
 * i3c_bus_normaluse_lock() for more details on what these normal operations
 * are.
 */
void i3c_bus_normaluse_unlock(struct i3c_bus *bus)
{}

static struct i3c_master_controller *
i3c_bus_to_i3c_master(struct i3c_bus *i3cbus)
{}

static struct i3c_master_controller *dev_to_i3cmaster(struct device *dev)
{}

static const struct device_type i3c_device_type;

static struct i3c_bus *dev_to_i3cbus(struct device *dev)
{}

static struct i3c_dev_desc *dev_to_i3cdesc(struct device *dev)
{}

static ssize_t bcr_show(struct device *dev,
			struct device_attribute *da,
			char *buf)
{}
static DEVICE_ATTR_RO(bcr);

static ssize_t dcr_show(struct device *dev,
			struct device_attribute *da,
			char *buf)
{}
static DEVICE_ATTR_RO(dcr);

static ssize_t pid_show(struct device *dev,
			struct device_attribute *da,
			char *buf)
{}
static DEVICE_ATTR_RO(pid);

static ssize_t dynamic_address_show(struct device *dev,
				    struct device_attribute *da,
				    char *buf)
{}
static DEVICE_ATTR_RO(dynamic_address);

static const char * const hdrcap_strings[] =;

static ssize_t hdrcap_show(struct device *dev,
			   struct device_attribute *da,
			   char *buf)
{}
static DEVICE_ATTR_RO(hdrcap);

static ssize_t modalias_show(struct device *dev,
			     struct device_attribute *da, char *buf)
{}
static DEVICE_ATTR_RO(modalias);

static struct attribute *i3c_device_attrs[] =;
ATTRIBUTE_GROUPS();

static int i3c_device_uevent(const struct device *dev, struct kobj_uevent_env *env)
{}

static const struct device_type i3c_device_type =;

static int i3c_device_match(struct device *dev, const struct device_driver *drv)
{}

static int i3c_device_probe(struct device *dev)
{}

static void i3c_device_remove(struct device *dev)
{}

const struct bus_type i3c_bus_type =;
EXPORT_SYMBOL_GPL();

static enum i3c_addr_slot_status
i3c_bus_get_addr_slot_status(struct i3c_bus *bus, u16 addr)
{}

static void i3c_bus_set_addr_slot_status(struct i3c_bus *bus, u16 addr,
					 enum i3c_addr_slot_status status)
{}

static bool i3c_bus_dev_addr_is_avail(struct i3c_bus *bus, u8 addr)
{}

static int i3c_bus_get_free_addr(struct i3c_bus *bus, u8 start_addr)
{}

static void i3c_bus_init_addrslots(struct i3c_bus *bus)
{}

static void i3c_bus_cleanup(struct i3c_bus *i3cbus)
{}

static int i3c_bus_init(struct i3c_bus *i3cbus, struct device_node *np)
{}

void i3c_for_each_bus_locked(int (*fn)(struct i3c_bus *bus, void *data),
			     void *data)
{}
EXPORT_SYMBOL_GPL();

int i3c_register_notifier(struct notifier_block *nb)
{}
EXPORT_SYMBOL_GPL();

int i3c_unregister_notifier(struct notifier_block *nb)
{}
EXPORT_SYMBOL_GPL();

static void i3c_bus_notify(struct i3c_bus *bus, unsigned int action)
{}

static const char * const i3c_bus_mode_strings[] =;

static ssize_t mode_show(struct device *dev,
			 struct device_attribute *da,
			 char *buf)
{}
static DEVICE_ATTR_RO(mode);

static ssize_t current_master_show(struct device *dev,
				   struct device_attribute *da,
				   char *buf)
{}
static DEVICE_ATTR_RO(current_master);

static ssize_t i3c_scl_frequency_show(struct device *dev,
				      struct device_attribute *da,
				      char *buf)
{}
static DEVICE_ATTR_RO(i3c_scl_frequency);

static ssize_t i2c_scl_frequency_show(struct device *dev,
				      struct device_attribute *da,
				      char *buf)
{}
static DEVICE_ATTR_RO(i2c_scl_frequency);

static int i3c_set_hotjoin(struct i3c_master_controller *master, bool enable)
{}

static ssize_t hotjoin_store(struct device *dev, struct device_attribute *attr,
			     const char *buf, size_t count)
{}

/*
 * i3c_master_enable_hotjoin - Enable hotjoin
 * @master: I3C master object
 *
 * Return: a 0 in case of success, an negative error code otherwise.
 */
int i3c_master_enable_hotjoin(struct i3c_master_controller *master)
{}
EXPORT_SYMBOL_GPL();

/*
 * i3c_master_disable_hotjoin - Disable hotjoin
 * @master: I3C master object
 *
 * Return: a 0 in case of success, an negative error code otherwise.
 */
int i3c_master_disable_hotjoin(struct i3c_master_controller *master)
{}
EXPORT_SYMBOL_GPL();

static ssize_t hotjoin_show(struct device *dev, struct device_attribute *da, char *buf)
{}

static DEVICE_ATTR_RW(hotjoin);

static struct attribute *i3c_masterdev_attrs[] =;
ATTRIBUTE_GROUPS();

static void i3c_masterdev_release(struct device *dev)
{}

static const struct device_type i3c_masterdev_type =;

static int i3c_bus_set_mode(struct i3c_bus *i3cbus, enum i3c_bus_mode mode,
			    unsigned long max_i2c_scl_rate)
{}

static struct i3c_master_controller *
i2c_adapter_to_i3c_master(struct i2c_adapter *adap)
{}

static struct i2c_adapter *
i3c_master_to_i2c_adapter(struct i3c_master_controller *master)
{}

static void i3c_master_free_i2c_dev(struct i2c_dev_desc *dev)
{}

static struct i2c_dev_desc *
i3c_master_alloc_i2c_dev(struct i3c_master_controller *master,
			 u16 addr, u8 lvr)
{}

static void *i3c_ccc_cmd_dest_init(struct i3c_ccc_cmd_dest *dest, u8 addr,
				   u16 payloadlen)
{}

static void i3c_ccc_cmd_dest_cleanup(struct i3c_ccc_cmd_dest *dest)
{}

static void i3c_ccc_cmd_init(struct i3c_ccc_cmd *cmd, bool rnw, u8 id,
			     struct i3c_ccc_cmd_dest *dests,
			     unsigned int ndests)
{}

static int i3c_master_send_ccc_cmd_locked(struct i3c_master_controller *master,
					  struct i3c_ccc_cmd *cmd)
{}

static struct i2c_dev_desc *
i3c_master_find_i2c_dev_by_addr(const struct i3c_master_controller *master,
				u16 addr)
{}

/**
 * i3c_master_get_free_addr() - get a free address on the bus
 * @master: I3C master object
 * @start_addr: where to start searching
 *
 * This function must be called with the bus lock held in write mode.
 *
 * Return: the first free address starting at @start_addr (included) or -ENOMEM
 * if there's no more address available.
 */
int i3c_master_get_free_addr(struct i3c_master_controller *master,
			     u8 start_addr)
{}
EXPORT_SYMBOL_GPL();

static void i3c_device_release(struct device *dev)
{}

static void i3c_master_free_i3c_dev(struct i3c_dev_desc *dev)
{}

static struct i3c_dev_desc *
i3c_master_alloc_i3c_dev(struct i3c_master_controller *master,
			 const struct i3c_device_info *info)
{}

static int i3c_master_rstdaa_locked(struct i3c_master_controller *master,
				    u8 addr)
{}

/**
 * i3c_master_entdaa_locked() - start a DAA (Dynamic Address Assignment)
 *				procedure
 * @master: master used to send frames on the bus
 *
 * Send a ENTDAA CCC command to start a DAA procedure.
 *
 * Note that this function only sends the ENTDAA CCC command, all the logic
 * behind dynamic address assignment has to be handled in the I3C master
 * driver.
 *
 * This function must be called with the bus lock held in write mode.
 *
 * Return: 0 in case of success, a positive I3C error code if the error is
 * one of the official Mx error codes, and a negative error code otherwise.
 */
int i3c_master_entdaa_locked(struct i3c_master_controller *master)
{}
EXPORT_SYMBOL_GPL();

static int i3c_master_enec_disec_locked(struct i3c_master_controller *master,
					u8 addr, bool enable, u8 evts)
{}

/**
 * i3c_master_disec_locked() - send a DISEC CCC command
 * @master: master used to send frames on the bus
 * @addr: a valid I3C slave address or %I3C_BROADCAST_ADDR
 * @evts: events to disable
 *
 * Send a DISEC CCC command to disable some or all events coming from a
 * specific slave, or all devices if @addr is %I3C_BROADCAST_ADDR.
 *
 * This function must be called with the bus lock held in write mode.
 *
 * Return: 0 in case of success, a positive I3C error code if the error is
 * one of the official Mx error codes, and a negative error code otherwise.
 */
int i3c_master_disec_locked(struct i3c_master_controller *master, u8 addr,
			    u8 evts)
{}
EXPORT_SYMBOL_GPL();

/**
 * i3c_master_enec_locked() - send an ENEC CCC command
 * @master: master used to send frames on the bus
 * @addr: a valid I3C slave address or %I3C_BROADCAST_ADDR
 * @evts: events to disable
 *
 * Sends an ENEC CCC command to enable some or all events coming from a
 * specific slave, or all devices if @addr is %I3C_BROADCAST_ADDR.
 *
 * This function must be called with the bus lock held in write mode.
 *
 * Return: 0 in case of success, a positive I3C error code if the error is
 * one of the official Mx error codes, and a negative error code otherwise.
 */
int i3c_master_enec_locked(struct i3c_master_controller *master, u8 addr,
			   u8 evts)
{}
EXPORT_SYMBOL_GPL();

/**
 * i3c_master_defslvs_locked() - send a DEFSLVS CCC command
 * @master: master used to send frames on the bus
 *
 * Send a DEFSLVS CCC command containing all the devices known to the @master.
 * This is useful when you have secondary masters on the bus to propagate
 * device information.
 *
 * This should be called after all I3C devices have been discovered (in other
 * words, after the DAA procedure has finished) and instantiated in
 * &i3c_master_controller_ops->bus_init().
 * It should also be called if a master ACKed an Hot-Join request and assigned
 * a dynamic address to the device joining the bus.
 *
 * This function must be called with the bus lock held in write mode.
 *
 * Return: 0 in case of success, a positive I3C error code if the error is
 * one of the official Mx error codes, and a negative error code otherwise.
 */
int i3c_master_defslvs_locked(struct i3c_master_controller *master)
{}
EXPORT_SYMBOL_GPL();

static int i3c_master_setda_locked(struct i3c_master_controller *master,
				   u8 oldaddr, u8 newaddr, bool setdasa)
{}

static int i3c_master_setdasa_locked(struct i3c_master_controller *master,
				     u8 static_addr, u8 dyn_addr)
{}

static int i3c_master_setnewda_locked(struct i3c_master_controller *master,
				      u8 oldaddr, u8 newaddr)
{}

static int i3c_master_getmrl_locked(struct i3c_master_controller *master,
				    struct i3c_device_info *info)
{}

static int i3c_master_getmwl_locked(struct i3c_master_controller *master,
				    struct i3c_device_info *info)
{}

static int i3c_master_getmxds_locked(struct i3c_master_controller *master,
				     struct i3c_device_info *info)
{}

static int i3c_master_gethdrcap_locked(struct i3c_master_controller *master,
				       struct i3c_device_info *info)
{}

static int i3c_master_getpid_locked(struct i3c_master_controller *master,
				    struct i3c_device_info *info)
{}

static int i3c_master_getbcr_locked(struct i3c_master_controller *master,
				    struct i3c_device_info *info)
{}

static int i3c_master_getdcr_locked(struct i3c_master_controller *master,
				    struct i3c_device_info *info)
{}

static int i3c_master_retrieve_dev_info(struct i3c_dev_desc *dev)
{}

static void i3c_master_put_i3c_addrs(struct i3c_dev_desc *dev)
{}

static int i3c_master_get_i3c_addrs(struct i3c_dev_desc *dev)
{}

static int i3c_master_attach_i3c_dev(struct i3c_master_controller *master,
				     struct i3c_dev_desc *dev)
{}

static int i3c_master_reattach_i3c_dev(struct i3c_dev_desc *dev,
				       u8 old_dyn_addr)
{}

static void i3c_master_detach_i3c_dev(struct i3c_dev_desc *dev)
{}

static int i3c_master_attach_i2c_dev(struct i3c_master_controller *master,
				     struct i2c_dev_desc *dev)
{}

static void i3c_master_detach_i2c_dev(struct i2c_dev_desc *dev)
{}

static int i3c_master_early_i3c_dev_add(struct i3c_master_controller *master,
					  struct i3c_dev_boardinfo *boardinfo)
{}

static void
i3c_master_register_new_i3c_devs(struct i3c_master_controller *master)
{}

/**
 * i3c_master_do_daa() - do a DAA (Dynamic Address Assignment)
 * @master: master doing the DAA
 *
 * This function is instantiating an I3C device object and adding it to the
 * I3C device list. All device information are automatically retrieved using
 * standard CCC commands.
 *
 * The I3C device object is returned in case the master wants to attach
 * private data to it using i3c_dev_set_master_data().
 *
 * This function must be called with the bus lock held in write mode.
 *
 * Return: a 0 in case of success, an negative error code otherwise.
 */
int i3c_master_do_daa(struct i3c_master_controller *master)
{}
EXPORT_SYMBOL_GPL();

/**
 * i3c_master_set_info() - set master device information
 * @master: master used to send frames on the bus
 * @info: I3C device information
 *
 * Set master device info. This should be called from
 * &i3c_master_controller_ops->bus_init().
 *
 * Not all &i3c_device_info fields are meaningful for a master device.
 * Here is a list of fields that should be properly filled:
 *
 * - &i3c_device_info->dyn_addr
 * - &i3c_device_info->bcr
 * - &i3c_device_info->dcr
 * - &i3c_device_info->pid
 * - &i3c_device_info->hdr_cap if %I3C_BCR_HDR_CAP bit is set in
 *   &i3c_device_info->bcr
 *
 * This function must be called with the bus lock held in maintenance mode.
 *
 * Return: 0 if @info contains valid information (not every piece of
 * information can be checked, but we can at least make sure @info->dyn_addr
 * and @info->bcr are correct), -EINVAL otherwise.
 */
int i3c_master_set_info(struct i3c_master_controller *master,
			const struct i3c_device_info *info)
{}
EXPORT_SYMBOL_GPL();

static void i3c_master_detach_free_devs(struct i3c_master_controller *master)
{}

/**
 * i3c_master_bus_init() - initialize an I3C bus
 * @master: main master initializing the bus
 *
 * This function is following all initialisation steps described in the I3C
 * specification:
 *
 * 1. Attach I2C devs to the master so that the master can fill its internal
 *    device table appropriately
 *
 * 2. Call &i3c_master_controller_ops->bus_init() method to initialize
 *    the master controller. That's usually where the bus mode is selected
 *    (pure bus or mixed fast/slow bus)
 *
 * 3. Instruct all devices on the bus to drop their dynamic address. This is
 *    particularly important when the bus was previously configured by someone
 *    else (for example the bootloader)
 *
 * 4. Disable all slave events.
 *
 * 5. Reserve address slots for I3C devices with init_dyn_addr. And if devices
 *    also have static_addr, try to pre-assign dynamic addresses requested by
 *    the FW with SETDASA and attach corresponding statically defined I3C
 *    devices to the master.
 *
 * 6. Do a DAA (Dynamic Address Assignment) to assign dynamic addresses to all
 *    remaining I3C devices
 *
 * Once this is done, all I3C and I2C devices should be usable.
 *
 * Return: a 0 in case of success, an negative error code otherwise.
 */
static int i3c_master_bus_init(struct i3c_master_controller *master)
{}

static void i3c_master_bus_cleanup(struct i3c_master_controller *master)
{}

static void i3c_master_attach_boardinfo(struct i3c_dev_desc *i3cdev)
{}

static struct i3c_dev_desc *
i3c_master_search_i3c_dev_duplicate(struct i3c_dev_desc *refdev)
{}

/**
 * i3c_master_add_i3c_dev_locked() - add an I3C slave to the bus
 * @master: master used to send frames on the bus
 * @addr: I3C slave dynamic address assigned to the device
 *
 * This function is instantiating an I3C device object and adding it to the
 * I3C device list. All device information are automatically retrieved using
 * standard CCC commands.
 *
 * The I3C device object is returned in case the master wants to attach
 * private data to it using i3c_dev_set_master_data().
 *
 * This function must be called with the bus lock held in write mode.
 *
 * Return: a 0 in case of success, an negative error code otherwise.
 */
int i3c_master_add_i3c_dev_locked(struct i3c_master_controller *master,
				  u8 addr)
{}
EXPORT_SYMBOL_GPL();

#define OF_I3C_REG1_IS_I2C_DEV

static int
of_i3c_master_add_i2c_boardinfo(struct i3c_master_controller *master,
				struct device_node *node, u32 *reg)
{}

static int
of_i3c_master_add_i3c_boardinfo(struct i3c_master_controller *master,
				struct device_node *node, u32 *reg)
{}

static int of_i3c_master_add_dev(struct i3c_master_controller *master,
				 struct device_node *node)
{}

static int of_populate_i3c_bus(struct i3c_master_controller *master)
{}

static int i3c_master_i2c_adapter_xfer(struct i2c_adapter *adap,
				       struct i2c_msg *xfers, int nxfers)
{}

static u32 i3c_master_i2c_funcs(struct i2c_adapter *adapter)
{}

static u8 i3c_master_i2c_get_lvr(struct i2c_client *client)
{}

static int i3c_master_i2c_attach(struct i2c_adapter *adap, struct i2c_client *client)
{}

static int i3c_master_i2c_detach(struct i2c_adapter *adap, struct i2c_client *client)
{}

static const struct i2c_algorithm i3c_master_i2c_algo =;

static int i3c_i2c_notifier_call(struct notifier_block *nb, unsigned long action,
				 void *data)
{}

static struct notifier_block i2cdev_notifier =;

static int i3c_master_i2c_adapter_init(struct i3c_master_controller *master)
{}

static void i3c_master_i2c_adapter_cleanup(struct i3c_master_controller *master)
{}

static void i3c_master_unregister_i3c_devs(struct i3c_master_controller *master)
{}

/**
 * i3c_master_queue_ibi() - Queue an IBI
 * @dev: the device this IBI is coming from
 * @slot: the IBI slot used to store the payload
 *
 * Queue an IBI to the controller workqueue. The IBI handler attached to
 * the dev will be called from a workqueue context.
 */
void i3c_master_queue_ibi(struct i3c_dev_desc *dev, struct i3c_ibi_slot *slot)
{}
EXPORT_SYMBOL_GPL();

static void i3c_master_handle_ibi(struct work_struct *work)
{}

static void i3c_master_init_ibi_slot(struct i3c_dev_desc *dev,
				     struct i3c_ibi_slot *slot)
{}

struct i3c_generic_ibi_slot {};

struct i3c_generic_ibi_pool {};

/**
 * i3c_generic_ibi_free_pool() - Free a generic IBI pool
 * @pool: the IBI pool to free
 *
 * Free all IBI slots allated by a generic IBI pool.
 */
void i3c_generic_ibi_free_pool(struct i3c_generic_ibi_pool *pool)
{}
EXPORT_SYMBOL_GPL();

/**
 * i3c_generic_ibi_alloc_pool() - Create a generic IBI pool
 * @dev: the device this pool will be used for
 * @req: IBI setup request describing what the device driver expects
 *
 * Create a generic IBI pool based on the information provided in @req.
 *
 * Return: a valid IBI pool in case of success, an ERR_PTR() otherwise.
 */
struct i3c_generic_ibi_pool *
i3c_generic_ibi_alloc_pool(struct i3c_dev_desc *dev,
			   const struct i3c_ibi_setup *req)
{}
EXPORT_SYMBOL_GPL();

/**
 * i3c_generic_ibi_get_free_slot() - Get a free slot from a generic IBI pool
 * @pool: the pool to query an IBI slot on
 *
 * Search for a free slot in a generic IBI pool.
 * The slot should be returned to the pool using i3c_generic_ibi_recycle_slot()
 * when it's no longer needed.
 *
 * Return: a pointer to a free slot, or NULL if there's no free slot available.
 */
struct i3c_ibi_slot *
i3c_generic_ibi_get_free_slot(struct i3c_generic_ibi_pool *pool)
{}
EXPORT_SYMBOL_GPL();

/**
 * i3c_generic_ibi_recycle_slot() - Return a slot to a generic IBI pool
 * @pool: the pool to return the IBI slot to
 * @s: IBI slot to recycle
 *
 * Add an IBI slot back to its generic IBI pool. Should be called from the
 * master driver struct_master_controller_ops->recycle_ibi() method.
 */
void i3c_generic_ibi_recycle_slot(struct i3c_generic_ibi_pool *pool,
				  struct i3c_ibi_slot *s)
{}
EXPORT_SYMBOL_GPL();

static int i3c_master_check_ops(const struct i3c_master_controller_ops *ops)
{}

/**
 * i3c_master_register() - register an I3C master
 * @master: master used to send frames on the bus
 * @parent: the parent device (the one that provides this I3C master
 *	    controller)
 * @ops: the master controller operations
 * @secondary: true if you are registering a secondary master. Will return
 *	       -ENOTSUPP if set to true since secondary masters are not yet
 *	       supported
 *
 * This function takes care of everything for you:
 *
 * - creates and initializes the I3C bus
 * - populates the bus with static I2C devs if @parent->of_node is not
 *   NULL
 * - registers all I3C devices added by the controller during bus
 *   initialization
 * - registers the I2C adapter and all I2C devices
 *
 * Return: 0 in case of success, a negative error code otherwise.
 */
int i3c_master_register(struct i3c_master_controller *master,
			struct device *parent,
			const struct i3c_master_controller_ops *ops,
			bool secondary)
{}
EXPORT_SYMBOL_GPL();

/**
 * i3c_master_unregister() - unregister an I3C master
 * @master: master used to send frames on the bus
 *
 * Basically undo everything done in i3c_master_register().
 */
void i3c_master_unregister(struct i3c_master_controller *master)
{}
EXPORT_SYMBOL_GPL();

int i3c_dev_setdasa_locked(struct i3c_dev_desc *dev)
{}

int i3c_dev_do_priv_xfers_locked(struct i3c_dev_desc *dev,
				 struct i3c_priv_xfer *xfers,
				 int nxfers)
{}

int i3c_dev_disable_ibi_locked(struct i3c_dev_desc *dev)
{}

int i3c_dev_enable_ibi_locked(struct i3c_dev_desc *dev)
{}

int i3c_dev_request_ibi_locked(struct i3c_dev_desc *dev,
			       const struct i3c_ibi_setup *req)
{}

void i3c_dev_free_ibi_locked(struct i3c_dev_desc *dev)
{}

static int __init i3c_init(void)
{}
subsys_initcall(i3c_init);

static void __exit i3c_exit(void)
{}
module_exit(i3c_exit);

MODULE_AUTHOR();
MODULE_DESCRIPTION();
MODULE_LICENSE();