drivers/i3c/device.c

Source file repositories/reference/linux-study-clean/drivers/i3c/device.c

File Facts

System
Linux kernel
Corpus path
drivers/i3c/device.c
Extension
.c
Size
8746 bytes
Lines
352
Domain
Driver Families
Bucket
drivers/i3c
Inferred role
Driver Families: exported/initcall integration point
Status
integration implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

// SPDX-License-Identifier: GPL-2.0
/*
 * Copyright (C) 2018 Cadence Design Systems Inc.
 *
 * Author: Boris Brezillon <boris.brezillon@bootlin.com>
 */

#include <linux/atomic.h>
#include <linux/bug.h>
#include <linux/completion.h>
#include <linux/device.h>
#include <linux/mutex.h>
#include <linux/slab.h>

#include "internals.h"

/**
 * i3c_device_do_xfers() - do I3C transfers directed to a specific device
 *
 * @dev: device with which the transfers should be done
 * @xfers: array of transfers
 * @nxfers: number of transfers
 * @mode: transfer mode
 *
 * Initiate one or several private SDR transfers with @dev.
 *
 * This function can sleep and thus cannot be called in atomic context.
 *
 * Return:
 * * 0 in case of success, a negative error core otherwise.
 * * -EAGAIN: controller lost address arbitration. Target (IBI, HJ or
 *   controller role request) win the bus. Client driver needs to resend the
 *   'xfers' some time later. See I3C spec ver 1.1.1 09-Jun-2021. Section:
 *   5.1.2.2.3.
 */
int i3c_device_do_xfers(struct i3c_device *dev, struct i3c_xfer *xfers,
			int nxfers, enum i3c_xfer_mode mode)
{
	int ret, i;

	if (nxfers < 1)
		return 0;

	for (i = 0; i < nxfers; i++) {
		if (!xfers[i].len || !xfers[i].data.in)
			return -EINVAL;
	}

	ret = i3c_bus_rpm_get(dev->bus);
	if (ret)
		return ret;

	i3c_bus_normaluse_lock(dev->bus);
	ret = i3c_dev_do_xfers_locked(dev->desc, xfers, nxfers, mode);
	i3c_bus_normaluse_unlock(dev->bus);

	i3c_bus_rpm_put(dev->bus);

	return ret;
}
EXPORT_SYMBOL_GPL(i3c_device_do_xfers);

/**
 * i3c_device_do_setdasa() - do I3C dynamic address assignement with
 *                           static address
 *
 * @dev: device with which the DAA should be done
 *
 * Return: 0 in case of success, a negative error core otherwise.
 */
int i3c_device_do_setdasa(struct i3c_device *dev)
{
	int ret;

	ret = i3c_bus_rpm_get(dev->bus);
	if (ret)
		return ret;

	i3c_bus_normaluse_lock(dev->bus);
	ret = i3c_dev_setdasa_locked(dev->desc);
	i3c_bus_normaluse_unlock(dev->bus);

	i3c_bus_rpm_put(dev->bus);

	return ret;
}
EXPORT_SYMBOL_GPL(i3c_device_do_setdasa);

/**
 * i3c_device_get_info() - get I3C device information

Annotation

Implementation Notes