4051 lines · 105.3 KB · C
RawDownload
// SPDX-License-Identifier: GPL-2.0/* * Copyright (C) 2018 Cadence Design Systems Inc. * * Author: Boris Brezillon <boris.brezillon@bootlin.com> */ #include <dt-bindings/i3c/i3c.h>#include <linux/acpi.h>#include <linux/atomic.h>#include <linux/bitmap.h>#include <linux/bug.h>#include <linux/delay.h>#include <linux/device.h>#include <linux/dma-mapping.h>#include <linux/err.h>#include <linux/export.h>#include <linux/i2c.h>#include <linux/kernel.h>#include <linux/list.h>#include <linux/of.h>#include <linux/of_device.h>#include <linux/pm_runtime.h>#include <linux/property.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){	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. */static void 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);} static struct i3c_master_controller *dev_to_i3cmaster(struct device *dev){	return container_of(dev, struct i3c_master_controller, dev);} static int __must_check i3c_master_rpm_get(struct i3c_master_controller *master){	int ret = master->rpm_allowed ? pm_runtime_resume_and_get(master->dev.parent) : 0; 	if (ret < 0) {		dev_err(master->dev.parent, "runtime resume failed, error %d\n", ret);		return ret;	}	return 0;} static void i3c_master_rpm_put(struct i3c_master_controller *master){	if (master->rpm_allowed)		pm_runtime_put_autosuspend(master->dev.parent);} int i3c_bus_rpm_get(struct i3c_bus *bus){	return i3c_master_rpm_get(i3c_bus_to_i3c_master(bus));} void i3c_bus_rpm_put(struct i3c_bus *bus){	i3c_master_rpm_put(i3c_bus_to_i3c_master(bus));} bool i3c_bus_rpm_ibi_allowed(struct i3c_bus *bus){	return i3c_bus_to_i3c_master(bus)->rpm_ibi_allowed;} static const struct device_type i3c_device_type; static struct i3c_bus *dev_to_i3cbus(struct device *dev){	struct i3c_master_controller *master; 	if (dev->type == &i3c_device_type)		return dev_to_i3cdev(dev)->bus; 	master = dev_to_i3cmaster(dev); 	return &master->bus;} static struct i3c_dev_desc *dev_to_i3cdesc(struct device *dev){	struct i3c_master_controller *master; 	if (dev->type == &i3c_device_type)		return dev_to_i3cdev(dev)->desc; 	master = dev_to_i3cmaster(dev); 	return master->this;} static ssize_t bcr_show(struct device *dev,			struct device_attribute *da,			char *buf){	struct i3c_bus *bus = dev_to_i3cbus(dev);	struct i3c_dev_desc *desc;	ssize_t ret; 	i3c_bus_normaluse_lock(bus);	desc = dev_to_i3cdesc(dev);	ret = sysfs_emit(buf, "0x%02x\n", desc->info.bcr);	i3c_bus_normaluse_unlock(bus); 	return ret;}static DEVICE_ATTR_RO(bcr); static ssize_t dcr_show(struct device *dev,			struct device_attribute *da,			char *buf){	struct i3c_bus *bus = dev_to_i3cbus(dev);	struct i3c_dev_desc *desc;	ssize_t ret; 	i3c_bus_normaluse_lock(bus);	desc = dev_to_i3cdesc(dev);	ret = sysfs_emit(buf, "0x%02x\n", desc->info.dcr);	i3c_bus_normaluse_unlock(bus); 	return ret;}static DEVICE_ATTR_RO(dcr); static ssize_t pid_show(struct device *dev,			struct device_attribute *da,			char *buf){	struct i3c_bus *bus = dev_to_i3cbus(dev);	struct i3c_dev_desc *desc;	ssize_t ret; 	i3c_bus_normaluse_lock(bus);	desc = dev_to_i3cdesc(dev);	ret = sysfs_emit(buf, "%llx\n", desc->info.pid);	i3c_bus_normaluse_unlock(bus); 	return ret;}static DEVICE_ATTR_RO(pid); static ssize_t dynamic_address_show(struct device *dev,				    struct device_attribute *da,				    char *buf){	struct i3c_bus *bus = dev_to_i3cbus(dev);	struct i3c_dev_desc *desc;	ssize_t ret; 	i3c_bus_normaluse_lock(bus);	desc = dev_to_i3cdesc(dev);	ret = sysfs_emit(buf, "%02x\n", desc->info.dyn_addr);	i3c_bus_normaluse_unlock(bus); 	return ret;}static DEVICE_ATTR_RO(dynamic_address); static const char * const hdrcap_strings[] = {	"hdr-ddr", "hdr-tsp", "hdr-tsl",}; static ssize_t hdrcap_show(struct device *dev,			   struct device_attribute *da,			   char *buf){	struct i3c_bus *bus = dev_to_i3cbus(dev);	struct i3c_dev_desc *desc;	ssize_t offset = 0, ret;	unsigned long caps;	int mode; 	i3c_bus_normaluse_lock(bus);	desc = dev_to_i3cdesc(dev);	caps = desc->info.hdr_cap;	for_each_set_bit(mode, &caps, 8) {		if (mode >= ARRAY_SIZE(hdrcap_strings))			break; 		if (!hdrcap_strings[mode])			continue; 		ret = sysfs_emit_at(buf, offset, offset ? " %s" : "%s",			      hdrcap_strings[mode]);		if (ret < 0)			goto out; 		offset += ret;	} 	ret = sysfs_emit_at(buf, offset, "\n");	if (ret < 0)		goto out; 	ret = offset + ret; out:	i3c_bus_normaluse_unlock(bus); 	return ret;}static DEVICE_ATTR_RO(hdrcap); static ssize_t modalias_show(struct device *dev,			     struct device_attribute *da, char *buf){	struct i3c_device *i3c = dev_to_i3cdev(dev);	struct i3c_device_info devinfo;	u16 manuf, part, ext; 	i3c_device_get_info(i3c, &devinfo);	manuf = I3C_PID_MANUF_ID(devinfo.pid);	part = I3C_PID_PART_ID(devinfo.pid);	ext = I3C_PID_EXTRA_INFO(devinfo.pid); 	if (I3C_PID_RND_LOWER_32BITS(devinfo.pid))		return sysfs_emit(buf, "i3c:dcr%02Xmanuf%04X\n", devinfo.dcr,			       manuf); 	return sysfs_emit(buf, "i3c:dcr%02Xmanuf%04Xpart%04Xext%04X\n",		       devinfo.dcr, manuf, part, ext);}static DEVICE_ATTR_RO(modalias); static struct attribute *i3c_device_attrs[] = {	&dev_attr_bcr.attr,	&dev_attr_dcr.attr,	&dev_attr_pid.attr,	&dev_attr_dynamic_address.attr,	&dev_attr_hdrcap.attr,	&dev_attr_modalias.attr,	NULL,};ATTRIBUTE_GROUPS(i3c_device); static int i3c_device_uevent(const struct device *dev, struct kobj_uevent_env *env){	const struct i3c_device *i3cdev = dev_to_i3cdev(dev);	struct i3c_device_info devinfo;	u16 manuf, part, ext; 	i3c_device_get_info(i3cdev, &devinfo);	manuf = I3C_PID_MANUF_ID(devinfo.pid);	part = I3C_PID_PART_ID(devinfo.pid);	ext = I3C_PID_EXTRA_INFO(devinfo.pid); 	if (I3C_PID_RND_LOWER_32BITS(devinfo.pid))		return add_uevent_var(env, "MODALIAS=i3c:dcr%02Xmanuf%04X",				      devinfo.dcr, manuf); 	return add_uevent_var(env,			      "MODALIAS=i3c:dcr%02Xmanuf%04Xpart%04Xext%04X",			      devinfo.dcr, manuf, part, ext);} static const struct device_type i3c_device_type = {	.groups	= i3c_device_groups,	.uevent = i3c_device_uevent,}; static int i3c_device_match(struct device *dev, const struct device_driver *drv){	struct i3c_device *i3cdev;	const struct i3c_driver *i3cdrv;	u8 static_addr_method = 0; 	if (dev->type != &i3c_device_type)		return 0; 	i3cdev = dev_to_i3cdev(dev);	i3cdrv = drv_to_i3cdrv(drv); 	i3c_bus_normaluse_lock(i3cdev->bus);	if (i3cdev->desc->boardinfo)		static_addr_method = i3cdev->desc->boardinfo->static_addr_method;	i3c_bus_normaluse_unlock(i3cdev->bus); 	/*	 * SETAASA-based devices need not always have a matching ID since	 * it is not mandatory for such devices to implement deviceinfo	 * CCC commands. Allow them to register through DT or ACPI.	 */	if (i3cdrv->id_table && i3c_device_match_id(i3cdev, i3cdrv->id_table))		return 1; 	if (static_addr_method & I3C_ADDR_METHOD_SETAASA) {		if (of_driver_match_device(dev, drv))			return 1;		if (acpi_driver_match_device(dev, drv))			return 1;	} 	return 0;} static int i3c_device_probe(struct device *dev){	struct i3c_device *i3cdev = dev_to_i3cdev(dev);	struct i3c_driver *driver = drv_to_i3cdrv(dev->driver); 	return driver->probe(i3cdev);} static void i3c_device_remove(struct device *dev){	struct i3c_device *i3cdev = dev_to_i3cdev(dev);	struct i3c_driver *driver = drv_to_i3cdrv(dev->driver); 	if (driver->remove)		driver->remove(i3cdev);} static enum i3c_addr_slot_statusi3c_bus_get_addr_slot_status_mask(struct i3c_bus *bus, u16 addr, u32 mask){	unsigned long status;	int bitpos = addr * I3C_ADDR_SLOT_STATUS_BITS; 	if (addr > I2C_MAX_ADDR)		return I3C_ADDR_SLOT_RSVD; 	status = bus->addrslots[bitpos / BITS_PER_LONG];	status >>= bitpos % BITS_PER_LONG; 	return status & mask;} static enum i3c_addr_slot_statusi3c_bus_get_addr_slot_status(struct i3c_bus *bus, u16 addr){	return i3c_bus_get_addr_slot_status_mask(bus, addr, I3C_ADDR_SLOT_STATUS_MASK);} static void i3c_bus_set_addr_slot_status_mask(struct i3c_bus *bus, u16 addr,					      enum i3c_addr_slot_status status, u32 mask){	int bitpos = addr * I3C_ADDR_SLOT_STATUS_BITS;	unsigned long *ptr; 	if (addr > I2C_MAX_ADDR)		return; 	ptr = bus->addrslots + (bitpos / BITS_PER_LONG);	*ptr &= ~((unsigned long)mask << (bitpos % BITS_PER_LONG));	*ptr |= ((unsigned long)status & mask) << (bitpos % BITS_PER_LONG);} static void i3c_bus_set_addr_slot_status(struct i3c_bus *bus, u16 addr,					 enum i3c_addr_slot_status status){	i3c_bus_set_addr_slot_status_mask(bus, addr, status, I3C_ADDR_SLOT_STATUS_MASK);} static bool i3c_bus_dev_addr_is_avail(struct i3c_bus *bus, u8 addr){	enum i3c_addr_slot_status status; 	status = i3c_bus_get_addr_slot_status(bus, addr); 	return status == I3C_ADDR_SLOT_FREE;} /* * ┌────┬─────────────┬───┬─────────┬───┐ * │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. */static int 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;} static void 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),

Lines 1–500 of 4051.