/** * 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.
*/ staticvoid i3c_bus_maintenance_lock(struct i3c_bus *bus)
{
down_write(&bus->lock);
}
/** * 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.
*/ staticvoid i3c_bus_maintenance_unlock(struct i3c_bus *bus)
{
up_write(&bus->lock);
}
/** * 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)
{
down_read(&bus->lock);
}
/** * 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)
{
up_read(&bus->lock);
}
/* * ┌────┬─────────────┬───┬─────────┬───┐ * │S/Sr│ 7'h7E RnW=0 │ACK│ ENTDAA │ T ├────┐ * └────┴─────────────┴───┴─────────┴───┘ │ * ┌─────────────────────────────────────────┘ * │ ┌──┬─────────────┬───┬─────────────────┬────────────────┬───┬─────────┐ * └─►│Sr│7'h7E RnW=1 │ACK│48bit UID BCR DCR│Assign 7bit Addr│PAR│ ACK/NACK│ * └──┴─────────────┴───┴─────────────────┴────────────────┴───┴─────────┘ * Some master controllers (such as HCI) need to prepare the entire above transaction before * sending it out to the I3C bus. This means that a 7-bit dynamic address needs to be allocated * before knowing the target device's UID information. * * However, some I3C targets may request specific addresses (called as "init_dyn_addr"), which is * typically specified by the DT-'s assigned-address property. Lower addresses having higher IBI * priority. If it is available, i3c_bus_get_free_addr() preferably return a free address that is * not in the list of desired addresses (called as "init_dyn_addr"). This allows the device with * the "init_dyn_addr" to switch to its "init_dyn_addr" when it hot-joins the I3C bus. Otherwise, * if the "init_dyn_addr" is already in use by another I3C device, the target device will not be * able to switch to its desired address. * * If the previous step fails, fallback returning one of the remaining unassigned address, * regardless of its state in the desired list.
*/ staticint i3c_bus_get_free_addr(struct i3c_bus *bus, u8 start_addr)
{ enum i3c_addr_slot_status status;
u8 addr;
for (addr = start_addr; addr < I3C_MAX_ADDR; addr++) {
status = i3c_bus_get_addr_slot_status_mask(bus, addr,
I3C_ADDR_SLOT_EXT_STATUS_MASK); if (status == I3C_ADDR_SLOT_FREE) return addr;
}
for (addr = start_addr; addr < I3C_MAX_ADDR; addr++) {
status = i3c_bus_get_addr_slot_status_mask(bus, addr,
I3C_ADDR_SLOT_STATUS_MASK); if (status == I3C_ADDR_SLOT_FREE) return addr;
}
return -ENOMEM;
}
staticvoid i3c_bus_init_addrslots(struct i3c_bus *bus)
{ int i;
/* Addresses 0 to 7 are reserved. */ for (i = 0; i < 8; i++)
i3c_bus_set_addr_slot_status(bus, i, I3C_ADDR_SLOT_RSVD);
/* * Reserve broadcast address and all addresses that might collide * with the broadcast address when facing a single bit error.
*/
i3c_bus_set_addr_slot_status(bus, I3C_BROADCAST_ADDR,
I3C_ADDR_SLOT_RSVD); for (i = 0; i < 7; i++)
i3c_bus_set_addr_slot_status(bus, I3C_BROADCAST_ADDR ^ BIT(i),
I3C_ADDR_SLOT_RSVD);
}
/* * I3C/I2C frequency may have been overridden, check that user-provided * values are not exceeding max possible frequency.
*/ if (i3cbus->scl_rate.i3c > I3C_BUS_I3C_SCL_MAX_RATE ||
i3cbus->scl_rate.i2c > I3C_BUS_I2C_FM_PLUS_SCL_MAX_RATE) return -EINVAL;
i3c_bus_for_each_i2cdev(&master->bus, dev) { if (dev->addr == addr) return dev;
}
return NULL;
}
/** * 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)
{ return i3c_bus_get_free_addr(&master->bus, start_addr);
}
EXPORT_SYMBOL_GPL(i3c_master_get_free_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)
{ struct i3c_ccc_cmd_dest dest; struct i3c_ccc_cmd cmd; int ret;
/** * 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)
{ return i3c_master_enec_disec_locked(master, addr, false, evts);
}
EXPORT_SYMBOL_GPL(i3c_master_disec_locked);
/** * 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)
{ return i3c_master_enec_disec_locked(master, addr, true, evts);
}
EXPORT_SYMBOL_GPL(i3c_master_enec_locked);
/** * 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)
{ struct i3c_ccc_defslvs *defslvs; struct i3c_ccc_dev_desc *desc; struct i3c_ccc_cmd_dest dest; struct i3c_dev_desc *i3cdev; struct i2c_dev_desc *i2cdev; struct i3c_ccc_cmd cmd; struct i3c_bus *bus; bool send = false; int ndevs = 0, ret;
if (!master) return -EINVAL;
bus = i3c_master_get_bus(master);
i3c_bus_for_each_i3cdev(bus, i3cdev) {
ndevs++;
if (i3cdev == master->this) continue;
if (I3C_BCR_DEVICE_ROLE(i3cdev->info.bcr) ==
I3C_BCR_I3C_MASTER)
send = true;
}
/* No other master on the bus, skip DEFSLVS. */ if (!send) return 0;
mrl = i3c_ccc_cmd_dest_init(&dest, info->dyn_addr, sizeof(*mrl)); if (!mrl) return -ENOMEM;
/* * When the device does not have IBI payload GETMRL only returns 2 * bytes of data.
*/ if (!(info->bcr & I3C_BCR_IBI_PAYLOAD))
dest.payload.len -= 1;
i3c_ccc_cmd_init(&cmd, true, I3C_CCC_GETMRL, &dest, 1);
ret = i3c_master_send_ccc_cmd_locked(master, &cmd); if (ret) goto out;
switch (dest.payload.len) { case 3:
info->max_ibi_len = mrl->ibi_len;
fallthrough; case 2:
info->max_read_len = be16_to_cpu(mrl->read_len); break; default:
ret = -EIO; goto out;
}
getmaxds = i3c_ccc_cmd_dest_init(&dest, info->dyn_addr, sizeof(*getmaxds)); if (!getmaxds) return -ENOMEM;
i3c_ccc_cmd_init(&cmd, true, I3C_CCC_GETMXDS, &dest, 1);
ret = i3c_master_send_ccc_cmd_locked(master, &cmd); if (ret) { /* * Retry when the device does not support max read turnaround * while expecting shorter length from this CCC command.
*/
dest.payload.len -= 3;
ret = i3c_master_send_ccc_cmd_locked(master, &cmd); if (ret) goto out;
}
if (dest.payload.len != 2 && dest.payload.len != 5) {
ret = -EIO; goto out;
}
if (!dev->info.static_addr && !dev->info.dyn_addr) return 0;
if (dev->info.static_addr) {
status = i3c_bus_get_addr_slot_status(&master->bus,
dev->info.static_addr); /* Since static address and assigned dynamic address can be * equal, allow this case to pass.
*/ if (status != I3C_ADDR_SLOT_FREE &&
dev->info.static_addr != dev->boardinfo->init_dyn_addr) return -EBUSY;
/* * ->init_dyn_addr should have been reserved before that, so, if we're * trying to apply a pre-reserved dynamic address, we should not try * to reserve the address slot a second time.
*/ if (dev->info.dyn_addr &&
(!dev->boardinfo ||
dev->boardinfo->init_dyn_addr != dev->info.dyn_addr)) {
status = i3c_bus_get_addr_slot_status(&master->bus,
dev->info.dyn_addr); if (status != I3C_ADDR_SLOT_FREE) goto err_release_static_addr;
err_release_static_addr: if (dev->info.static_addr)
i3c_bus_set_addr_slot_status(&master->bus,
dev->info.static_addr,
I3C_ADDR_SLOT_FREE);
return -EBUSY;
}
staticint i3c_master_attach_i3c_dev(struct i3c_master_controller *master, struct i3c_dev_desc *dev)
{ int ret;
/* * We don't attach devices to the controller until they are * addressable on the bus.
*/ if (!dev->info.static_addr && !dev->info.dyn_addr) return 0;
ret = i3c_master_get_i3c_addrs(dev); if (ret) return ret;
/* Do not attach the master device itself. */ if (master->this != dev && master->ops->attach_i3c_dev) {
ret = master->ops->attach_i3c_dev(dev); if (ret) {
i3c_master_put_i3c_addrs(dev); return ret;
}
}
if (desc->boardinfo)
desc->dev->dev.of_node = desc->boardinfo->of_node;
ret = device_register(&desc->dev->dev); if (ret) {
dev_err(&master->dev, "Failed to add I3C device (err = %d)\n", ret);
put_device(&desc->dev->dev);
}
}
}
/** * 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)
{ int ret;
i3c_bus_maintenance_lock(&master->bus);
ret = master->ops->do_daa(master);
i3c_bus_maintenance_unlock(&master->bus);
/** * 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, conststruct i3c_device_info *info)
{ struct i3c_dev_desc *i3cdev; int ret;
if (!i3c_bus_dev_addr_is_avail(&master->bus, info->dyn_addr)) return -EINVAL;
if (I3C_BCR_DEVICE_ROLE(info->bcr) == I3C_BCR_I3C_MASTER &&
master->secondary) return -EINVAL;
if (master->this) return -EINVAL;
i3cdev = i3c_master_alloc_i3c_dev(master, info); if (IS_ERR(i3cdev)) return PTR_ERR(i3cdev);
/**
* 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)
{
enum i3c_addr_slot_status status;
struct i2c_dev_boardinfo *i2cboardinfo;
struct i3c_dev_boardinfo *i3cboardinfo;
struct i2c_dev_desc *i2cdev;
int ret;
/*
* First attach all devices with static definitions provided by the
* FW.
*/
list_for_each_entry(i2cboardinfo, &master->boardinfo.i2c, node) {
status = i3c_bus_get_addr_slot_status(&master->bus,
i2cboardinfo->base.addr);
if (status != I3C_ADDR_SLOT_FREE) {
ret = -EBUSY;
goto err_detach_devs;
}
i2cdev = i3c_master_alloc_i2c_dev(master,
i2cboardinfo->base.addr,
i2cboardinfo->lvr);
if (IS_ERR(i2cdev)) {
ret = PTR_ERR(i2cdev);
goto err_detach_devs;
}
ret = i3c_master_attach_i2c_dev(master, i2cdev);
if (ret) {
i3c_master_free_i2c_dev(i2cdev);
goto err_detach_devs;
}
}
/*
* Now execute the controller specific ->bus_init() routine, which
* might configure its internal logic to match the bus limitations.
*/
ret = master->ops->bus_init(master);
if (ret)
goto err_detach_devs;
/*
* The master device should have been instantiated in ->bus_init(),
* complain if this was not the case.
*/
if (!master->this) {
dev_err(&master->dev,
"master_set_info() was not called in ->bus_init()\n");
ret = -EINVAL;
goto err_bus_cleanup;
}
if (master->ops->set_speed) {
ret = master->ops->set_speed(master, I3C_OPEN_DRAIN_SLOW_SPEED);
if (ret)
goto err_bus_cleanup;
}
/*
* Reset all dynamic address that may have been assigned before
* (assigned by the bootloader for example).
*/
ret = i3c_master_rstdaa_locked(master, I3C_BROADCAST_ADDR);
if (ret && ret != I3C_ERROR_M2)
goto err_bus_cleanup;
if (master->ops->set_speed) {
ret = master->ops->set_speed(master, I3C_OPEN_DRAIN_NORMAL_SPEED);
if (ret)
goto err_bus_cleanup;
}
/* Disable all slave events before starting DAA. */
ret = i3c_master_disec_locked(master, I3C_BROADCAST_ADDR,
I3C_CCC_EVENT_SIR | I3C_CCC_EVENT_MR |
I3C_CCC_EVENT_HJ);
if (ret && ret != I3C_ERROR_M2)
goto err_bus_cleanup;
/*
* Reserve init_dyn_addr first, and then try to pre-assign dynamic
* address and retrieve device information if needed.
* In case pre-assign dynamic address fails, setting dynamic address to
* the requested init_dyn_addr is retried after DAA is done in
* i3c_master_add_i3c_dev_locked().
*/
list_for_each_entry(i3cboardinfo, &master->boardinfo.i3c, node) {
/*
* We don't reserve a dynamic address for devices that
* don't explicitly request one.
*/
if (!i3cboardinfo->init_dyn_addr)
continue;
ret = i3c_bus_get_addr_slot_status(&master->bus,
i3cboardinfo->init_dyn_addr);
if (ret != I3C_ADDR_SLOT_FREE) {
ret = -EBUSY;
goto err_rstdaa;
}
/* Do not mark as occupied until real device exist in bus */
i3c_bus_set_addr_slot_status_mask(&master->bus,
i3cboardinfo->init_dyn_addr,
I3C_ADDR_SLOT_EXT_DESIRED,
I3C_ADDR_SLOT_EXT_STATUS_MASK);
/*
* Only try to create/attach devices that have a static
* address. Other devices will be created/attached when
* DAA happens, and the requested dynamic address will
* be set using SETNEWDA once those devices become
* addressable.
*/
if (i3cboardinfo->static_addr)
i3c_master_early_i3c_dev_add(master, i3cboardinfo);
}
ret = i3c_master_do_daa(master);
if (ret)
goto err_rstdaa;
/**
* 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)
{
struct i3c_device_info info = { .dyn_addr = addr };
struct i3c_dev_desc *newdev, *olddev;
u8 old_dyn_addr = addr, expected_dyn_addr;
struct i3c_ibi_setup ibireq = { };
bool enable_ibi = false;
int ret;
if (!master)
return -EINVAL;
newdev = i3c_master_alloc_i3c_dev(master, &info);
if (IS_ERR(newdev))
return PTR_ERR(newdev);
ret = i3c_master_attach_i3c_dev(master, newdev);
if (ret)
goto err_free_dev;
ret = i3c_master_retrieve_dev_info(newdev);
if (ret)
goto err_detach_dev;
i3c_master_attach_boardinfo(newdev);
olddev = i3c_master_search_i3c_dev_duplicate(newdev);
if (olddev) {
newdev->dev = olddev->dev;
if (newdev->dev)
newdev->dev->desc = newdev;
/*
* We need to restore the IBI state too, so let's save the
* IBI information and try to restore them after olddev has
* been detached+released and its IBI has been stopped and
* the associated resources have been freed.
*/
mutex_lock(&olddev->ibi_lock);
if (olddev->ibi) {
ibireq.handler = olddev->ibi->handler;
ibireq.max_payload_len = olddev->ibi->max_payload_len;
ibireq.num_slots = olddev->ibi->num_slots;
if (olddev->ibi->enabled)
enable_ibi = true;
/*
* The olddev should not receive any commands on the
* i3c bus as it does not exist and has been assigned
* a new address. This will result in NACK or timeout.
* So, update the olddev->ibi->enabled flag to false
* to avoid DISEC with OldAddr.
*/
olddev->ibi->enabled = false;
i3c_dev_free_ibi_locked(olddev);
}
mutex_unlock(&olddev->ibi_lock);
/*
* Depending on our previous state, the expected dynamic address might
* differ:
* - if the device already had a dynamic address assigned, let's try to
* re-apply this one
* - if the device did not have a dynamic address and the firmware
* requested a specific address, pick this one
* - in any other case, keep the address automatically assigned by the
* master
*/
if (old_dyn_addr && old_dyn_addr != newdev->info.dyn_addr)
expected_dyn_addr = old_dyn_addr;
else if (newdev->boardinfo && newdev->boardinfo->init_dyn_addr)
expected_dyn_addr = newdev->boardinfo->init_dyn_addr;
else
expected_dyn_addr = newdev->info.dyn_addr;
if (newdev->info.dyn_addr != expected_dyn_addr &&
i3c_bus_get_addr_slot_status(&master->bus, expected_dyn_addr) == I3C_ADDR_SLOT_FREE) {
/*
* Try to apply the expected dynamic address. If it fails, keep
* the address assigned by the master.
*/
ret = i3c_master_setnewda_locked(master,
newdev->info.dyn_addr,
expected_dyn_addr);
if (!ret) {
old_dyn_addr = newdev->info.dyn_addr;
newdev->info.dyn_addr = expected_dyn_addr;
i3c_master_reattach_i3c_dev(newdev, old_dyn_addr);
} else {
dev_err(&master->dev,
"Failed to assign reserved/old address to device %d%llx",
master->bus.id, newdev->info.pid);
}
}
/*
* Now is time to try to restore the IBI setup. If we're lucky,
* everything works as before, otherwise, all we can do is complain.
* FIXME: maybe we should add callback to inform the driver that it
* should request the IBI again instead of trying to hide that from
* him.
*/
if (ibireq.handler) {
mutex_lock(&newdev->ibi_lock);
ret = i3c_dev_request_ibi_locked(newdev, &ibireq);
if (ret) {
dev_err(&master->dev,
"Failed to request IBI on device %d-%llx",
master->bus.id, newdev->info.pid);
} else if (enable_ibi) {
ret = i3c_dev_enable_ibi_locked(newdev);
if (ret)
dev_err(&master->dev,
"Failed to re-enable IBI on device %d-%llx",
master->bus.id, newdev->info.pid);
}
mutex_unlock(&newdev->ibi_lock);
}
return 0;
err_detach_dev:
if (newdev->dev && newdev->dev->desc)
newdev->dev->desc = NULL;
boardinfo = devm_kzalloc(dev, sizeof(*boardinfo), GFP_KERNEL);
if (!boardinfo)
return -ENOMEM;
ret = of_i2c_get_board_info(dev, node, &boardinfo->base);
if (ret)
return ret;
/*
* The I3C Specification does not clearly say I2C devices with 10-bit
* address are supported. These devices can't be passed properly through
* DEFSLVS command.
*/
if (boardinfo->base.flags & I2C_CLIENT_TEN) {
dev_err(dev, "I2C device with 10 bit address not supported.");
return -EOPNOTSUPP;
}
/* LVR is encoded in reg[2]. */
boardinfo->lvr = reg[2];
static int of_i3c_master_add_dev(struct i3c_master_controller *master,
struct device_node *node)
{
u32 reg[3];
int ret;
if (!master)
return -EINVAL;
ret = of_property_read_u32_array(node, "reg", reg, ARRAY_SIZE(reg));
if (ret)
return ret;
/*
* The manufacturer ID can't be 0. If reg[1] == 0 that means we're
* dealing with an I2C device.
*/
if (!reg[1])
ret = of_i3c_master_add_i2c_boardinfo(master, node, reg);
else
ret = of_i3c_master_add_i3c_boardinfo(master, node, reg);
for_each_available_child_of_node(i3cbus_np, node) {
ret = of_i3c_master_add_dev(master, node);
if (ret) {
of_node_put(node);
return ret;
}
}
/*
* The user might want to limit I2C and I3C speed in case some devices
* on the bus are not supporting typical rates, or if the bus topology
* prevents it from using max possible rate.
*/
if (!of_property_read_u32(i3cbus_np, "i2c-scl-hz", &val))
master->bus.scl_rate.i2c = val;
if (!of_property_read_u32(i3cbus_np, "i3c-scl-hz", &val))
master->bus.scl_rate.i3c = val;
return 0;
}
static int i3c_master_i2c_adapter_xfer(struct i2c_adapter *adap,
struct i2c_msg *xfers, int nxfers)
{
struct i3c_master_controller *master = i2c_adapter_to_i3c_master(adap);
struct i2c_dev_desc *dev;
int i, ret;
u16 addr;
if (!xfers || !master || nxfers <= 0)
return -EINVAL;
if (!master->ops->i2c_xfers)
return -EOPNOTSUPP;
/* Doing transfers to different devices is not supported. */
addr = xfers[0].addr;
for (i = 1; i < nxfers; i++) {
if (addr != xfers[i].addr)
return -EOPNOTSUPP;
}
i3c_bus_normaluse_lock(&master->bus);
dev = i3c_master_find_i2c_dev_by_addr(master, addr);
if (!dev)
ret = -ENOENT;
else
ret = master->ops->i2c_xfers(dev, xfers, nxfers);
i3c_bus_normaluse_unlock(&master->bus);
static u8 i3c_master_i2c_get_lvr(struct i2c_client *client)
{
/* Fall back to no spike filters and FM bus mode. */
u8 lvr = I3C_LVR_I2C_INDEX(2) | I3C_LVR_I2C_FM_MODE;
u32 reg[3];
if (!of_property_read_u32_array(client->dev.of_node, "reg", reg, ARRAY_SIZE(reg)))
lvr = reg[2];
i3c_bus_maintenance_lock(&master->bus);
switch (action) {
case BUS_NOTIFY_ADD_DEVICE:
ret = i3c_master_i2c_attach(adap, client);
break;
case BUS_NOTIFY_DEL_DEVICE:
ret = i3c_master_i2c_detach(adap, client);
break;
default:
ret = -EINVAL;
}
i3c_bus_maintenance_unlock(&master->bus);
/* FIXME: Should we allow i3c masters to override these values? */
adap->timeout = HZ;
adap->retries = 3;
id = of_alias_get_id(master->dev.of_node, "i2c");
if (id >= 0) {
adap->nr = id;
ret = i2c_add_numbered_adapter(adap);
} else {
ret = i2c_add_adapter(adap);
}
if (ret)
return ret;
/*
* We silently ignore failures here. The bus should keep working
* correctly even if one or more i2c devices are not registered.
*/
list_for_each_entry(i2cboardinfo, &master->boardinfo.i2c, node) {
i2cdev = i3c_master_find_i2c_dev_by_addr(master,
i2cboardinfo->base.addr);
if (WARN_ON(!i2cdev))
continue;
i2cdev->dev = i2c_new_client_device(adap, &i2cboardinfo->base);
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.