13a379bbcSBoris Brezillon // SPDX-License-Identifier: GPL-2.0
23a379bbcSBoris Brezillon /*
33a379bbcSBoris Brezillon * Copyright (C) 2018 Cadence Design Systems Inc.
43a379bbcSBoris Brezillon *
53a379bbcSBoris Brezillon * Author: Boris Brezillon <boris.brezillon@bootlin.com>
63a379bbcSBoris Brezillon */
73a379bbcSBoris Brezillon
83a379bbcSBoris Brezillon #include <linux/atomic.h>
93a379bbcSBoris Brezillon #include <linux/bug.h>
103a379bbcSBoris Brezillon #include <linux/device.h>
113a379bbcSBoris Brezillon #include <linux/err.h>
123a379bbcSBoris Brezillon #include <linux/export.h>
133a379bbcSBoris Brezillon #include <linux/kernel.h>
143a379bbcSBoris Brezillon #include <linux/list.h>
153a379bbcSBoris Brezillon #include <linux/of.h>
163a379bbcSBoris Brezillon #include <linux/slab.h>
173a379bbcSBoris Brezillon #include <linux/spinlock.h>
183a379bbcSBoris Brezillon #include <linux/workqueue.h>
193a379bbcSBoris Brezillon
203a379bbcSBoris Brezillon #include "internals.h"
213a379bbcSBoris Brezillon
223a379bbcSBoris Brezillon static DEFINE_IDR(i3c_bus_idr);
233a379bbcSBoris Brezillon static DEFINE_MUTEX(i3c_core_lock);
247dc2e0a8SJeremy Kerr static int __i3c_first_dynamic_bus_num;
254edeb9faSJeremy Kerr static BLOCKING_NOTIFIER_HEAD(i3c_bus_notifier);
263a379bbcSBoris Brezillon
273a379bbcSBoris Brezillon /**
283a379bbcSBoris Brezillon * i3c_bus_maintenance_lock - Lock the bus for a maintenance operation
293a379bbcSBoris Brezillon * @bus: I3C bus to take the lock on
303a379bbcSBoris Brezillon *
313a379bbcSBoris Brezillon * This function takes the bus lock so that no other operations can occur on
323a379bbcSBoris Brezillon * the bus. This is needed for all kind of bus maintenance operation, like
333a379bbcSBoris Brezillon * - enabling/disabling slave events
343a379bbcSBoris Brezillon * - re-triggering DAA
353a379bbcSBoris Brezillon * - changing the dynamic address of a device
363a379bbcSBoris Brezillon * - relinquishing mastership
373a379bbcSBoris Brezillon * - ...
383a379bbcSBoris Brezillon *
393a379bbcSBoris Brezillon * The reason for this kind of locking is that we don't want drivers and core
403a379bbcSBoris Brezillon * logic to rely on I3C device information that could be changed behind their
413a379bbcSBoris Brezillon * back.
423a379bbcSBoris Brezillon */
i3c_bus_maintenance_lock(struct i3c_bus * bus)433a379bbcSBoris Brezillon static void i3c_bus_maintenance_lock(struct i3c_bus *bus)
443a379bbcSBoris Brezillon {
453a379bbcSBoris Brezillon down_write(&bus->lock);
463a379bbcSBoris Brezillon }
473a379bbcSBoris Brezillon
483a379bbcSBoris Brezillon /**
493a379bbcSBoris Brezillon * i3c_bus_maintenance_unlock - Release the bus lock after a maintenance
503a379bbcSBoris Brezillon * operation
513a379bbcSBoris Brezillon * @bus: I3C bus to release the lock on
523a379bbcSBoris Brezillon *
533a379bbcSBoris Brezillon * Should be called when the bus maintenance operation is done. See
543a379bbcSBoris Brezillon * i3c_bus_maintenance_lock() for more details on what these maintenance
553a379bbcSBoris Brezillon * operations are.
563a379bbcSBoris Brezillon */
i3c_bus_maintenance_unlock(struct i3c_bus * bus)573a379bbcSBoris Brezillon static void i3c_bus_maintenance_unlock(struct i3c_bus *bus)
583a379bbcSBoris Brezillon {
593a379bbcSBoris Brezillon up_write(&bus->lock);
603a379bbcSBoris Brezillon }
613a379bbcSBoris Brezillon
623a379bbcSBoris Brezillon /**
633a379bbcSBoris Brezillon * i3c_bus_normaluse_lock - Lock the bus for a normal operation
643a379bbcSBoris Brezillon * @bus: I3C bus to take the lock on
653a379bbcSBoris Brezillon *
663a379bbcSBoris Brezillon * This function takes the bus lock for any operation that is not a maintenance
673a379bbcSBoris Brezillon * operation (see i3c_bus_maintenance_lock() for a non-exhaustive list of
683a379bbcSBoris Brezillon * maintenance operations). Basically all communications with I3C devices are
693a379bbcSBoris Brezillon * normal operations (HDR, SDR transfers or CCC commands that do not change bus
703a379bbcSBoris Brezillon * state or I3C dynamic address).
713a379bbcSBoris Brezillon *
723a379bbcSBoris Brezillon * Note that this lock is not guaranteeing serialization of normal operations.
733a379bbcSBoris Brezillon * In other words, transfer requests passed to the I3C master can be submitted
743a379bbcSBoris Brezillon * in parallel and I3C master drivers have to use their own locking to make
753a379bbcSBoris Brezillon * sure two different communications are not inter-mixed, or access to the
763a379bbcSBoris Brezillon * output/input queue is not done while the engine is busy.
773a379bbcSBoris Brezillon */
i3c_bus_normaluse_lock(struct i3c_bus * bus)783a379bbcSBoris Brezillon void i3c_bus_normaluse_lock(struct i3c_bus *bus)
793a379bbcSBoris Brezillon {
803a379bbcSBoris Brezillon down_read(&bus->lock);
813a379bbcSBoris Brezillon }
823a379bbcSBoris Brezillon
833a379bbcSBoris Brezillon /**
843a379bbcSBoris Brezillon * i3c_bus_normaluse_unlock - Release the bus lock after a normal operation
853a379bbcSBoris Brezillon * @bus: I3C bus to release the lock on
863a379bbcSBoris Brezillon *
873a379bbcSBoris Brezillon * Should be called when a normal operation is done. See
883a379bbcSBoris Brezillon * i3c_bus_normaluse_lock() for more details on what these normal operations
893a379bbcSBoris Brezillon * are.
903a379bbcSBoris Brezillon */
i3c_bus_normaluse_unlock(struct i3c_bus * bus)913a379bbcSBoris Brezillon void i3c_bus_normaluse_unlock(struct i3c_bus *bus)
923a379bbcSBoris Brezillon {
933a379bbcSBoris Brezillon up_read(&bus->lock);
943a379bbcSBoris Brezillon }
953a379bbcSBoris Brezillon
96ecc8fb54SVitor Soares static struct i3c_master_controller *
i3c_bus_to_i3c_master(struct i3c_bus * i3cbus)97ecc8fb54SVitor Soares i3c_bus_to_i3c_master(struct i3c_bus *i3cbus)
98ecc8fb54SVitor Soares {
99ecc8fb54SVitor Soares return container_of(i3cbus, struct i3c_master_controller, bus);
100ecc8fb54SVitor Soares }
101ecc8fb54SVitor Soares
dev_to_i3cmaster(struct device * dev)1023a379bbcSBoris Brezillon static struct i3c_master_controller *dev_to_i3cmaster(struct device *dev)
1033a379bbcSBoris Brezillon {
1043a379bbcSBoris Brezillon return container_of(dev, struct i3c_master_controller, dev);
1053a379bbcSBoris Brezillon }
1063a379bbcSBoris Brezillon
1073a379bbcSBoris Brezillon static const struct device_type i3c_device_type;
1083a379bbcSBoris Brezillon
dev_to_i3cbus(struct device * dev)1093a379bbcSBoris Brezillon static struct i3c_bus *dev_to_i3cbus(struct device *dev)
1103a379bbcSBoris Brezillon {
1113a379bbcSBoris Brezillon struct i3c_master_controller *master;
1123a379bbcSBoris Brezillon
1133a379bbcSBoris Brezillon if (dev->type == &i3c_device_type)
1143a379bbcSBoris Brezillon return dev_to_i3cdev(dev)->bus;
1153a379bbcSBoris Brezillon
1163a379bbcSBoris Brezillon master = dev_to_i3cmaster(dev);
1173a379bbcSBoris Brezillon
1183a379bbcSBoris Brezillon return &master->bus;
1193a379bbcSBoris Brezillon }
1203a379bbcSBoris Brezillon
dev_to_i3cdesc(struct device * dev)1213a379bbcSBoris Brezillon static struct i3c_dev_desc *dev_to_i3cdesc(struct device *dev)
1223a379bbcSBoris Brezillon {
1233a379bbcSBoris Brezillon struct i3c_master_controller *master;
1243a379bbcSBoris Brezillon
1253a379bbcSBoris Brezillon if (dev->type == &i3c_device_type)
1263a379bbcSBoris Brezillon return dev_to_i3cdev(dev)->desc;
1273a379bbcSBoris Brezillon
1286030f42dSAxel Lin master = dev_to_i3cmaster(dev);
1293a379bbcSBoris Brezillon
1303a379bbcSBoris Brezillon return master->this;
1313a379bbcSBoris Brezillon }
1323a379bbcSBoris Brezillon
bcr_show(struct device * dev,struct device_attribute * da,char * buf)1333a379bbcSBoris Brezillon static ssize_t bcr_show(struct device *dev,
1343a379bbcSBoris Brezillon struct device_attribute *da,
1353a379bbcSBoris Brezillon char *buf)
1363a379bbcSBoris Brezillon {
1373a379bbcSBoris Brezillon struct i3c_bus *bus = dev_to_i3cbus(dev);
1383a379bbcSBoris Brezillon struct i3c_dev_desc *desc;
1393a379bbcSBoris Brezillon ssize_t ret;
1403a379bbcSBoris Brezillon
1413a379bbcSBoris Brezillon i3c_bus_normaluse_lock(bus);
1423a379bbcSBoris Brezillon desc = dev_to_i3cdesc(dev);
1433a379bbcSBoris Brezillon ret = sprintf(buf, "%x\n", desc->info.bcr);
1443a379bbcSBoris Brezillon i3c_bus_normaluse_unlock(bus);
1453a379bbcSBoris Brezillon
1463a379bbcSBoris Brezillon return ret;
1473a379bbcSBoris Brezillon }
1483a379bbcSBoris Brezillon static DEVICE_ATTR_RO(bcr);
1493a379bbcSBoris Brezillon
dcr_show(struct device * dev,struct device_attribute * da,char * buf)1503a379bbcSBoris Brezillon static ssize_t dcr_show(struct device *dev,
1513a379bbcSBoris Brezillon struct device_attribute *da,
1523a379bbcSBoris Brezillon char *buf)
1533a379bbcSBoris Brezillon {
1543a379bbcSBoris Brezillon struct i3c_bus *bus = dev_to_i3cbus(dev);
1553a379bbcSBoris Brezillon struct i3c_dev_desc *desc;
1563a379bbcSBoris Brezillon ssize_t ret;
1573a379bbcSBoris Brezillon
1583a379bbcSBoris Brezillon i3c_bus_normaluse_lock(bus);
1593a379bbcSBoris Brezillon desc = dev_to_i3cdesc(dev);
1603a379bbcSBoris Brezillon ret = sprintf(buf, "%x\n", desc->info.dcr);
1613a379bbcSBoris Brezillon i3c_bus_normaluse_unlock(bus);
1623a379bbcSBoris Brezillon
1633a379bbcSBoris Brezillon return ret;
1643a379bbcSBoris Brezillon }
1653a379bbcSBoris Brezillon static DEVICE_ATTR_RO(dcr);
1663a379bbcSBoris Brezillon
pid_show(struct device * dev,struct device_attribute * da,char * buf)1673a379bbcSBoris Brezillon static ssize_t pid_show(struct device *dev,
1683a379bbcSBoris Brezillon struct device_attribute *da,
1693a379bbcSBoris Brezillon char *buf)
1703a379bbcSBoris Brezillon {
1713a379bbcSBoris Brezillon struct i3c_bus *bus = dev_to_i3cbus(dev);
1723a379bbcSBoris Brezillon struct i3c_dev_desc *desc;
1733a379bbcSBoris Brezillon ssize_t ret;
1743a379bbcSBoris Brezillon
1753a379bbcSBoris Brezillon i3c_bus_normaluse_lock(bus);
1763a379bbcSBoris Brezillon desc = dev_to_i3cdesc(dev);
1773a379bbcSBoris Brezillon ret = sprintf(buf, "%llx\n", desc->info.pid);
1783a379bbcSBoris Brezillon i3c_bus_normaluse_unlock(bus);
1793a379bbcSBoris Brezillon
1803a379bbcSBoris Brezillon return ret;
1813a379bbcSBoris Brezillon }
1823a379bbcSBoris Brezillon static DEVICE_ATTR_RO(pid);
1833a379bbcSBoris Brezillon
dynamic_address_show(struct device * dev,struct device_attribute * da,char * buf)1843a379bbcSBoris Brezillon static ssize_t dynamic_address_show(struct device *dev,
1853a379bbcSBoris Brezillon struct device_attribute *da,
1863a379bbcSBoris Brezillon char *buf)
1873a379bbcSBoris Brezillon {
1883a379bbcSBoris Brezillon struct i3c_bus *bus = dev_to_i3cbus(dev);
1893a379bbcSBoris Brezillon struct i3c_dev_desc *desc;
1903a379bbcSBoris Brezillon ssize_t ret;
1913a379bbcSBoris Brezillon
1923a379bbcSBoris Brezillon i3c_bus_normaluse_lock(bus);
1933a379bbcSBoris Brezillon desc = dev_to_i3cdesc(dev);
1943a379bbcSBoris Brezillon ret = sprintf(buf, "%02x\n", desc->info.dyn_addr);
1953a379bbcSBoris Brezillon i3c_bus_normaluse_unlock(bus);
1963a379bbcSBoris Brezillon
1973a379bbcSBoris Brezillon return ret;
1983a379bbcSBoris Brezillon }
1993a379bbcSBoris Brezillon static DEVICE_ATTR_RO(dynamic_address);
2003a379bbcSBoris Brezillon
2013a379bbcSBoris Brezillon static const char * const hdrcap_strings[] = {
2023a379bbcSBoris Brezillon "hdr-ddr", "hdr-tsp", "hdr-tsl",
2033a379bbcSBoris Brezillon };
2043a379bbcSBoris Brezillon
hdrcap_show(struct device * dev,struct device_attribute * da,char * buf)2053a379bbcSBoris Brezillon static ssize_t hdrcap_show(struct device *dev,
2063a379bbcSBoris Brezillon struct device_attribute *da,
2073a379bbcSBoris Brezillon char *buf)
2083a379bbcSBoris Brezillon {
2093a379bbcSBoris Brezillon struct i3c_bus *bus = dev_to_i3cbus(dev);
2103a379bbcSBoris Brezillon struct i3c_dev_desc *desc;
2113a379bbcSBoris Brezillon ssize_t offset = 0, ret;
2123a379bbcSBoris Brezillon unsigned long caps;
2133a379bbcSBoris Brezillon int mode;
2143a379bbcSBoris Brezillon
2153a379bbcSBoris Brezillon i3c_bus_normaluse_lock(bus);
2163a379bbcSBoris Brezillon desc = dev_to_i3cdesc(dev);
2173a379bbcSBoris Brezillon caps = desc->info.hdr_cap;
2183a379bbcSBoris Brezillon for_each_set_bit(mode, &caps, 8) {
2193a379bbcSBoris Brezillon if (mode >= ARRAY_SIZE(hdrcap_strings))
2203a379bbcSBoris Brezillon break;
2213a379bbcSBoris Brezillon
2223a379bbcSBoris Brezillon if (!hdrcap_strings[mode])
2233a379bbcSBoris Brezillon continue;
2243a379bbcSBoris Brezillon
2253a379bbcSBoris Brezillon ret = sprintf(buf + offset, offset ? " %s" : "%s",
2263a379bbcSBoris Brezillon hdrcap_strings[mode]);
2273a379bbcSBoris Brezillon if (ret < 0)
2283a379bbcSBoris Brezillon goto out;
2293a379bbcSBoris Brezillon
2303a379bbcSBoris Brezillon offset += ret;
2313a379bbcSBoris Brezillon }
2323a379bbcSBoris Brezillon
2333a379bbcSBoris Brezillon ret = sprintf(buf + offset, "\n");
2343a379bbcSBoris Brezillon if (ret < 0)
2353a379bbcSBoris Brezillon goto out;
2363a379bbcSBoris Brezillon
2373a379bbcSBoris Brezillon ret = offset + ret;
2383a379bbcSBoris Brezillon
2393a379bbcSBoris Brezillon out:
2403a379bbcSBoris Brezillon i3c_bus_normaluse_unlock(bus);
2413a379bbcSBoris Brezillon
2423a379bbcSBoris Brezillon return ret;
2433a379bbcSBoris Brezillon }
2443a379bbcSBoris Brezillon static DEVICE_ATTR_RO(hdrcap);
2453a379bbcSBoris Brezillon
modalias_show(struct device * dev,struct device_attribute * da,char * buf)2467ec0ddb0SBoris Brezillon static ssize_t modalias_show(struct device *dev,
2477ec0ddb0SBoris Brezillon struct device_attribute *da, char *buf)
2487ec0ddb0SBoris Brezillon {
2497ec0ddb0SBoris Brezillon struct i3c_device *i3c = dev_to_i3cdev(dev);
2507ec0ddb0SBoris Brezillon struct i3c_device_info devinfo;
2517ec0ddb0SBoris Brezillon u16 manuf, part, ext;
2527ec0ddb0SBoris Brezillon
2537ec0ddb0SBoris Brezillon i3c_device_get_info(i3c, &devinfo);
2547ec0ddb0SBoris Brezillon manuf = I3C_PID_MANUF_ID(devinfo.pid);
2557ec0ddb0SBoris Brezillon part = I3C_PID_PART_ID(devinfo.pid);
2567ec0ddb0SBoris Brezillon ext = I3C_PID_EXTRA_INFO(devinfo.pid);
2577ec0ddb0SBoris Brezillon
2587ec0ddb0SBoris Brezillon if (I3C_PID_RND_LOWER_32BITS(devinfo.pid))
2597ec0ddb0SBoris Brezillon return sprintf(buf, "i3c:dcr%02Xmanuf%04X", devinfo.dcr,
2607ec0ddb0SBoris Brezillon manuf);
2617ec0ddb0SBoris Brezillon
2627ec0ddb0SBoris Brezillon return sprintf(buf, "i3c:dcr%02Xmanuf%04Xpart%04Xext%04X",
2637ec0ddb0SBoris Brezillon devinfo.dcr, manuf, part, ext);
2647ec0ddb0SBoris Brezillon }
2657ec0ddb0SBoris Brezillon static DEVICE_ATTR_RO(modalias);
2667ec0ddb0SBoris Brezillon
2673a379bbcSBoris Brezillon static struct attribute *i3c_device_attrs[] = {
2683a379bbcSBoris Brezillon &dev_attr_bcr.attr,
2693a379bbcSBoris Brezillon &dev_attr_dcr.attr,
2703a379bbcSBoris Brezillon &dev_attr_pid.attr,
2713a379bbcSBoris Brezillon &dev_attr_dynamic_address.attr,
2723a379bbcSBoris Brezillon &dev_attr_hdrcap.attr,
2737ec0ddb0SBoris Brezillon &dev_attr_modalias.attr,
2743a379bbcSBoris Brezillon NULL,
2753a379bbcSBoris Brezillon };
2763a379bbcSBoris Brezillon ATTRIBUTE_GROUPS(i3c_device);
2773a379bbcSBoris Brezillon
i3c_device_uevent(const struct device * dev,struct kobj_uevent_env * env)278162736b0SGreg Kroah-Hartman static int i3c_device_uevent(const struct device *dev, struct kobj_uevent_env *env)
2793a379bbcSBoris Brezillon {
280162736b0SGreg Kroah-Hartman const struct i3c_device *i3cdev = dev_to_i3cdev(dev);
2813a379bbcSBoris Brezillon struct i3c_device_info devinfo;
2823a379bbcSBoris Brezillon u16 manuf, part, ext;
2833a379bbcSBoris Brezillon
2843a379bbcSBoris Brezillon i3c_device_get_info(i3cdev, &devinfo);
2853a379bbcSBoris Brezillon manuf = I3C_PID_MANUF_ID(devinfo.pid);
2863a379bbcSBoris Brezillon part = I3C_PID_PART_ID(devinfo.pid);
2873a379bbcSBoris Brezillon ext = I3C_PID_EXTRA_INFO(devinfo.pid);
2883a379bbcSBoris Brezillon
2893a379bbcSBoris Brezillon if (I3C_PID_RND_LOWER_32BITS(devinfo.pid))
2903a379bbcSBoris Brezillon return add_uevent_var(env, "MODALIAS=i3c:dcr%02Xmanuf%04X",
2913a379bbcSBoris Brezillon devinfo.dcr, manuf);
2923a379bbcSBoris Brezillon
2933a379bbcSBoris Brezillon return add_uevent_var(env,
29412e21a23SBoris Brezillon "MODALIAS=i3c:dcr%02Xmanuf%04Xpart%04Xext%04X",
2953a379bbcSBoris Brezillon devinfo.dcr, manuf, part, ext);
2963a379bbcSBoris Brezillon }
2973a379bbcSBoris Brezillon
2983a379bbcSBoris Brezillon static const struct device_type i3c_device_type = {
2993a379bbcSBoris Brezillon .groups = i3c_device_groups,
3003a379bbcSBoris Brezillon .uevent = i3c_device_uevent,
3013a379bbcSBoris Brezillon };
3023a379bbcSBoris Brezillon
i3c_device_match(struct device * dev,struct device_driver * drv)3033a379bbcSBoris Brezillon static int i3c_device_match(struct device *dev, struct device_driver *drv)
3043a379bbcSBoris Brezillon {
3053a379bbcSBoris Brezillon struct i3c_device *i3cdev;
3063a379bbcSBoris Brezillon struct i3c_driver *i3cdrv;
3073a379bbcSBoris Brezillon
3083a379bbcSBoris Brezillon if (dev->type != &i3c_device_type)
3093a379bbcSBoris Brezillon return 0;
3103a379bbcSBoris Brezillon
3113a379bbcSBoris Brezillon i3cdev = dev_to_i3cdev(dev);
3123a379bbcSBoris Brezillon i3cdrv = drv_to_i3cdrv(drv);
3133a379bbcSBoris Brezillon if (i3c_device_match_id(i3cdev, i3cdrv->id_table))
3143a379bbcSBoris Brezillon return 1;
3153a379bbcSBoris Brezillon
3163a379bbcSBoris Brezillon return 0;
3173a379bbcSBoris Brezillon }
3183a379bbcSBoris Brezillon
i3c_device_probe(struct device * dev)3193a379bbcSBoris Brezillon static int i3c_device_probe(struct device *dev)
3203a379bbcSBoris Brezillon {
3213a379bbcSBoris Brezillon struct i3c_device *i3cdev = dev_to_i3cdev(dev);
3223a379bbcSBoris Brezillon struct i3c_driver *driver = drv_to_i3cdrv(dev->driver);
3233a379bbcSBoris Brezillon
3243a379bbcSBoris Brezillon return driver->probe(i3cdev);
3253a379bbcSBoris Brezillon }
3263a379bbcSBoris Brezillon
i3c_device_remove(struct device * dev)327fc7a6209SUwe Kleine-König static void i3c_device_remove(struct device *dev)
3283a379bbcSBoris Brezillon {
3293a379bbcSBoris Brezillon struct i3c_device *i3cdev = dev_to_i3cdev(dev);
3303a379bbcSBoris Brezillon struct i3c_driver *driver = drv_to_i3cdrv(dev->driver);
3313a379bbcSBoris Brezillon
332dd926703SUwe Kleine-König if (driver->remove)
333dd926703SUwe Kleine-König driver->remove(i3cdev);
3343a379bbcSBoris Brezillon
3353a379bbcSBoris Brezillon i3c_device_free_ibi(i3cdev);
3363a379bbcSBoris Brezillon }
3373a379bbcSBoris Brezillon
3383a379bbcSBoris Brezillon struct bus_type i3c_bus_type = {
3393a379bbcSBoris Brezillon .name = "i3c",
3403a379bbcSBoris Brezillon .match = i3c_device_match,
3413a379bbcSBoris Brezillon .probe = i3c_device_probe,
3423a379bbcSBoris Brezillon .remove = i3c_device_remove,
3433a379bbcSBoris Brezillon };
3443a379bbcSBoris Brezillon
3453a379bbcSBoris Brezillon static enum i3c_addr_slot_status
i3c_bus_get_addr_slot_status(struct i3c_bus * bus,u16 addr)3463a379bbcSBoris Brezillon i3c_bus_get_addr_slot_status(struct i3c_bus *bus, u16 addr)
3473a379bbcSBoris Brezillon {
348f18f9811SJamie Iles unsigned long status;
349f18f9811SJamie Iles int bitpos = addr * 2;
3503a379bbcSBoris Brezillon
3513a379bbcSBoris Brezillon if (addr > I2C_MAX_ADDR)
3523a379bbcSBoris Brezillon return I3C_ADDR_SLOT_RSVD;
3533a379bbcSBoris Brezillon
3543a379bbcSBoris Brezillon status = bus->addrslots[bitpos / BITS_PER_LONG];
3553a379bbcSBoris Brezillon status >>= bitpos % BITS_PER_LONG;
3563a379bbcSBoris Brezillon
3573a379bbcSBoris Brezillon return status & I3C_ADDR_SLOT_STATUS_MASK;
3583a379bbcSBoris Brezillon }
3593a379bbcSBoris Brezillon
i3c_bus_set_addr_slot_status(struct i3c_bus * bus,u16 addr,enum i3c_addr_slot_status status)3603a379bbcSBoris Brezillon static void i3c_bus_set_addr_slot_status(struct i3c_bus *bus, u16 addr,
3613a379bbcSBoris Brezillon enum i3c_addr_slot_status status)
3623a379bbcSBoris Brezillon {
3633a379bbcSBoris Brezillon int bitpos = addr * 2;
3643a379bbcSBoris Brezillon unsigned long *ptr;
3653a379bbcSBoris Brezillon
3663a379bbcSBoris Brezillon if (addr > I2C_MAX_ADDR)
3673a379bbcSBoris Brezillon return;
3683a379bbcSBoris Brezillon
3693a379bbcSBoris Brezillon ptr = bus->addrslots + (bitpos / BITS_PER_LONG);
370476c7e1dSDan Carpenter *ptr &= ~((unsigned long)I3C_ADDR_SLOT_STATUS_MASK <<
371476c7e1dSDan Carpenter (bitpos % BITS_PER_LONG));
372476c7e1dSDan Carpenter *ptr |= (unsigned long)status << (bitpos % BITS_PER_LONG);
3733a379bbcSBoris Brezillon }
3743a379bbcSBoris Brezillon
i3c_bus_dev_addr_is_avail(struct i3c_bus * bus,u8 addr)3753a379bbcSBoris Brezillon static bool i3c_bus_dev_addr_is_avail(struct i3c_bus *bus, u8 addr)
3763a379bbcSBoris Brezillon {
3773a379bbcSBoris Brezillon enum i3c_addr_slot_status status;
3783a379bbcSBoris Brezillon
3793a379bbcSBoris Brezillon status = i3c_bus_get_addr_slot_status(bus, addr);
3803a379bbcSBoris Brezillon
3813a379bbcSBoris Brezillon return status == I3C_ADDR_SLOT_FREE;
3823a379bbcSBoris Brezillon }
3833a379bbcSBoris Brezillon
i3c_bus_get_free_addr(struct i3c_bus * bus,u8 start_addr)3843a379bbcSBoris Brezillon static int i3c_bus_get_free_addr(struct i3c_bus *bus, u8 start_addr)
3853a379bbcSBoris Brezillon {
3863a379bbcSBoris Brezillon enum i3c_addr_slot_status status;
3873a379bbcSBoris Brezillon u8 addr;
3883a379bbcSBoris Brezillon
3893a379bbcSBoris Brezillon for (addr = start_addr; addr < I3C_MAX_ADDR; addr++) {
3903a379bbcSBoris Brezillon status = i3c_bus_get_addr_slot_status(bus, addr);
3913a379bbcSBoris Brezillon if (status == I3C_ADDR_SLOT_FREE)
3923a379bbcSBoris Brezillon return addr;
3933a379bbcSBoris Brezillon }
3943a379bbcSBoris Brezillon
3953a379bbcSBoris Brezillon return -ENOMEM;
3963a379bbcSBoris Brezillon }
3973a379bbcSBoris Brezillon
i3c_bus_init_addrslots(struct i3c_bus * bus)3983a379bbcSBoris Brezillon static void i3c_bus_init_addrslots(struct i3c_bus *bus)
3993a379bbcSBoris Brezillon {
4003a379bbcSBoris Brezillon int i;
4013a379bbcSBoris Brezillon
4023a379bbcSBoris Brezillon /* Addresses 0 to 7 are reserved. */
4033a379bbcSBoris Brezillon for (i = 0; i < 8; i++)
4043a379bbcSBoris Brezillon i3c_bus_set_addr_slot_status(bus, i, I3C_ADDR_SLOT_RSVD);
4053a379bbcSBoris Brezillon
4063a379bbcSBoris Brezillon /*
4073a379bbcSBoris Brezillon * Reserve broadcast address and all addresses that might collide
4083a379bbcSBoris Brezillon * with the broadcast address when facing a single bit error.
4093a379bbcSBoris Brezillon */
4103a379bbcSBoris Brezillon i3c_bus_set_addr_slot_status(bus, I3C_BROADCAST_ADDR,
4113a379bbcSBoris Brezillon I3C_ADDR_SLOT_RSVD);
4123a379bbcSBoris Brezillon for (i = 0; i < 7; i++)
4133a379bbcSBoris Brezillon i3c_bus_set_addr_slot_status(bus, I3C_BROADCAST_ADDR ^ BIT(i),
4143a379bbcSBoris Brezillon I3C_ADDR_SLOT_RSVD);
4153a379bbcSBoris Brezillon }
4163a379bbcSBoris Brezillon
i3c_bus_cleanup(struct i3c_bus * i3cbus)4173a379bbcSBoris Brezillon static void i3c_bus_cleanup(struct i3c_bus *i3cbus)
4183a379bbcSBoris Brezillon {
4193a379bbcSBoris Brezillon mutex_lock(&i3c_core_lock);
4203a379bbcSBoris Brezillon idr_remove(&i3c_bus_idr, i3cbus->id);
4213a379bbcSBoris Brezillon mutex_unlock(&i3c_core_lock);
4223a379bbcSBoris Brezillon }
4233a379bbcSBoris Brezillon
i3c_bus_init(struct i3c_bus * i3cbus,struct device_node * np)4247dc2e0a8SJeremy Kerr static int i3c_bus_init(struct i3c_bus *i3cbus, struct device_node *np)
4253a379bbcSBoris Brezillon {
4267dc2e0a8SJeremy Kerr int ret, start, end, id = -1;
4273a379bbcSBoris Brezillon
4283a379bbcSBoris Brezillon init_rwsem(&i3cbus->lock);
4293a379bbcSBoris Brezillon INIT_LIST_HEAD(&i3cbus->devs.i2c);
4303a379bbcSBoris Brezillon INIT_LIST_HEAD(&i3cbus->devs.i3c);
4313a379bbcSBoris Brezillon i3c_bus_init_addrslots(i3cbus);
4323a379bbcSBoris Brezillon i3cbus->mode = I3C_BUS_MODE_PURE;
4333a379bbcSBoris Brezillon
4347dc2e0a8SJeremy Kerr if (np)
4357dc2e0a8SJeremy Kerr id = of_alias_get_id(np, "i3c");
4367dc2e0a8SJeremy Kerr
4373a379bbcSBoris Brezillon mutex_lock(&i3c_core_lock);
4387dc2e0a8SJeremy Kerr if (id >= 0) {
4397dc2e0a8SJeremy Kerr start = id;
4407dc2e0a8SJeremy Kerr end = start + 1;
4417dc2e0a8SJeremy Kerr } else {
4427dc2e0a8SJeremy Kerr start = __i3c_first_dynamic_bus_num;
4437dc2e0a8SJeremy Kerr end = 0;
4447dc2e0a8SJeremy Kerr }
4457dc2e0a8SJeremy Kerr
4467dc2e0a8SJeremy Kerr ret = idr_alloc(&i3c_bus_idr, i3cbus, start, end, GFP_KERNEL);
4473a379bbcSBoris Brezillon mutex_unlock(&i3c_core_lock);
4483a379bbcSBoris Brezillon
4493a379bbcSBoris Brezillon if (ret < 0)
4503a379bbcSBoris Brezillon return ret;
4513a379bbcSBoris Brezillon
4523a379bbcSBoris Brezillon i3cbus->id = ret;
4533a379bbcSBoris Brezillon
4543a379bbcSBoris Brezillon return 0;
4553a379bbcSBoris Brezillon }
4563a379bbcSBoris Brezillon
i3c_for_each_bus_locked(int (* fn)(struct i3c_bus * bus,void * data),void * data)4574edeb9faSJeremy Kerr void i3c_for_each_bus_locked(int (*fn)(struct i3c_bus *bus, void *data),
4584edeb9faSJeremy Kerr void *data)
4594edeb9faSJeremy Kerr {
4604edeb9faSJeremy Kerr struct i3c_bus *bus;
4614edeb9faSJeremy Kerr int id;
4624edeb9faSJeremy Kerr
4634edeb9faSJeremy Kerr mutex_lock(&i3c_core_lock);
4644edeb9faSJeremy Kerr idr_for_each_entry(&i3c_bus_idr, bus, id)
4654edeb9faSJeremy Kerr fn(bus, data);
4664edeb9faSJeremy Kerr mutex_unlock(&i3c_core_lock);
4674edeb9faSJeremy Kerr }
4684edeb9faSJeremy Kerr EXPORT_SYMBOL_GPL(i3c_for_each_bus_locked);
4694edeb9faSJeremy Kerr
i3c_register_notifier(struct notifier_block * nb)4704edeb9faSJeremy Kerr int i3c_register_notifier(struct notifier_block *nb)
4714edeb9faSJeremy Kerr {
4724edeb9faSJeremy Kerr return blocking_notifier_chain_register(&i3c_bus_notifier, nb);
4734edeb9faSJeremy Kerr }
4744edeb9faSJeremy Kerr EXPORT_SYMBOL_GPL(i3c_register_notifier);
4754edeb9faSJeremy Kerr
i3c_unregister_notifier(struct notifier_block * nb)4764edeb9faSJeremy Kerr int i3c_unregister_notifier(struct notifier_block *nb)
4774edeb9faSJeremy Kerr {
4784edeb9faSJeremy Kerr return blocking_notifier_chain_unregister(&i3c_bus_notifier, nb);
4794edeb9faSJeremy Kerr }
4804edeb9faSJeremy Kerr EXPORT_SYMBOL_GPL(i3c_unregister_notifier);
4814edeb9faSJeremy Kerr
i3c_bus_notify(struct i3c_bus * bus,unsigned int action)4824edeb9faSJeremy Kerr static void i3c_bus_notify(struct i3c_bus *bus, unsigned int action)
4834edeb9faSJeremy Kerr {
4844edeb9faSJeremy Kerr blocking_notifier_call_chain(&i3c_bus_notifier, action, bus);
4854edeb9faSJeremy Kerr }
4864edeb9faSJeremy Kerr
4873a379bbcSBoris Brezillon static const char * const i3c_bus_mode_strings[] = {
4883a379bbcSBoris Brezillon [I3C_BUS_MODE_PURE] = "pure",
4893a379bbcSBoris Brezillon [I3C_BUS_MODE_MIXED_FAST] = "mixed-fast",
490cbf4f732SVitor Soares [I3C_BUS_MODE_MIXED_LIMITED] = "mixed-limited",
4913a379bbcSBoris Brezillon [I3C_BUS_MODE_MIXED_SLOW] = "mixed-slow",
4923a379bbcSBoris Brezillon };
4933a379bbcSBoris Brezillon
mode_show(struct device * dev,struct device_attribute * da,char * buf)4943a379bbcSBoris Brezillon static ssize_t mode_show(struct device *dev,
4953a379bbcSBoris Brezillon struct device_attribute *da,
4963a379bbcSBoris Brezillon char *buf)
4973a379bbcSBoris Brezillon {
4983a379bbcSBoris Brezillon struct i3c_bus *i3cbus = dev_to_i3cbus(dev);
4993a379bbcSBoris Brezillon ssize_t ret;
5003a379bbcSBoris Brezillon
5013a379bbcSBoris Brezillon i3c_bus_normaluse_lock(i3cbus);
5023a379bbcSBoris Brezillon if (i3cbus->mode < 0 ||
503afe120c7SDan Carpenter i3cbus->mode >= ARRAY_SIZE(i3c_bus_mode_strings) ||
5043a379bbcSBoris Brezillon !i3c_bus_mode_strings[i3cbus->mode])
5053a379bbcSBoris Brezillon ret = sprintf(buf, "unknown\n");
5063a379bbcSBoris Brezillon else
5073a379bbcSBoris Brezillon ret = sprintf(buf, "%s\n", i3c_bus_mode_strings[i3cbus->mode]);
5083a379bbcSBoris Brezillon i3c_bus_normaluse_unlock(i3cbus);
5093a379bbcSBoris Brezillon
5103a379bbcSBoris Brezillon return ret;
5113a379bbcSBoris Brezillon }
5123a379bbcSBoris Brezillon static DEVICE_ATTR_RO(mode);
5133a379bbcSBoris Brezillon
current_master_show(struct device * dev,struct device_attribute * da,char * buf)5143a379bbcSBoris Brezillon static ssize_t current_master_show(struct device *dev,
5153a379bbcSBoris Brezillon struct device_attribute *da,
5163a379bbcSBoris Brezillon char *buf)
5173a379bbcSBoris Brezillon {
5183a379bbcSBoris Brezillon struct i3c_bus *i3cbus = dev_to_i3cbus(dev);
5193a379bbcSBoris Brezillon ssize_t ret;
5203a379bbcSBoris Brezillon
5213a379bbcSBoris Brezillon i3c_bus_normaluse_lock(i3cbus);
5223a379bbcSBoris Brezillon ret = sprintf(buf, "%d-%llx\n", i3cbus->id,
5233a379bbcSBoris Brezillon i3cbus->cur_master->info.pid);
5243a379bbcSBoris Brezillon i3c_bus_normaluse_unlock(i3cbus);
5253a379bbcSBoris Brezillon
5263a379bbcSBoris Brezillon return ret;
5273a379bbcSBoris Brezillon }
5283a379bbcSBoris Brezillon static DEVICE_ATTR_RO(current_master);
5293a379bbcSBoris Brezillon
i3c_scl_frequency_show(struct device * dev,struct device_attribute * da,char * buf)5303a379bbcSBoris Brezillon static ssize_t i3c_scl_frequency_show(struct device *dev,
5313a379bbcSBoris Brezillon struct device_attribute *da,
5323a379bbcSBoris Brezillon char *buf)
5333a379bbcSBoris Brezillon {
5343a379bbcSBoris Brezillon struct i3c_bus *i3cbus = dev_to_i3cbus(dev);
5353a379bbcSBoris Brezillon ssize_t ret;
5363a379bbcSBoris Brezillon
5373a379bbcSBoris Brezillon i3c_bus_normaluse_lock(i3cbus);
5383a379bbcSBoris Brezillon ret = sprintf(buf, "%ld\n", i3cbus->scl_rate.i3c);
5393a379bbcSBoris Brezillon i3c_bus_normaluse_unlock(i3cbus);
5403a379bbcSBoris Brezillon
5413a379bbcSBoris Brezillon return ret;
5423a379bbcSBoris Brezillon }
5433a379bbcSBoris Brezillon static DEVICE_ATTR_RO(i3c_scl_frequency);
5443a379bbcSBoris Brezillon
i2c_scl_frequency_show(struct device * dev,struct device_attribute * da,char * buf)5453a379bbcSBoris Brezillon static ssize_t i2c_scl_frequency_show(struct device *dev,
5463a379bbcSBoris Brezillon struct device_attribute *da,
5473a379bbcSBoris Brezillon char *buf)
5483a379bbcSBoris Brezillon {
5493a379bbcSBoris Brezillon struct i3c_bus *i3cbus = dev_to_i3cbus(dev);
5503a379bbcSBoris Brezillon ssize_t ret;
5513a379bbcSBoris Brezillon
5523a379bbcSBoris Brezillon i3c_bus_normaluse_lock(i3cbus);
5533a379bbcSBoris Brezillon ret = sprintf(buf, "%ld\n", i3cbus->scl_rate.i2c);
5543a379bbcSBoris Brezillon i3c_bus_normaluse_unlock(i3cbus);
5553a379bbcSBoris Brezillon
5563a379bbcSBoris Brezillon return ret;
5573a379bbcSBoris Brezillon }
5583a379bbcSBoris Brezillon static DEVICE_ATTR_RO(i2c_scl_frequency);
5593a379bbcSBoris Brezillon
5603a379bbcSBoris Brezillon static struct attribute *i3c_masterdev_attrs[] = {
5613a379bbcSBoris Brezillon &dev_attr_mode.attr,
5623a379bbcSBoris Brezillon &dev_attr_current_master.attr,
5633a379bbcSBoris Brezillon &dev_attr_i3c_scl_frequency.attr,
5643a379bbcSBoris Brezillon &dev_attr_i2c_scl_frequency.attr,
5653a379bbcSBoris Brezillon &dev_attr_bcr.attr,
5663a379bbcSBoris Brezillon &dev_attr_dcr.attr,
5673a379bbcSBoris Brezillon &dev_attr_pid.attr,
5683a379bbcSBoris Brezillon &dev_attr_dynamic_address.attr,
5693a379bbcSBoris Brezillon &dev_attr_hdrcap.attr,
5703a379bbcSBoris Brezillon NULL,
5713a379bbcSBoris Brezillon };
5723a379bbcSBoris Brezillon ATTRIBUTE_GROUPS(i3c_masterdev);
5733a379bbcSBoris Brezillon
i3c_masterdev_release(struct device * dev)5743a379bbcSBoris Brezillon static void i3c_masterdev_release(struct device *dev)
5753a379bbcSBoris Brezillon {
5763a379bbcSBoris Brezillon struct i3c_master_controller *master = dev_to_i3cmaster(dev);
5773a379bbcSBoris Brezillon struct i3c_bus *bus = dev_to_i3cbus(dev);
5783a379bbcSBoris Brezillon
5793a379bbcSBoris Brezillon if (master->wq)
5803a379bbcSBoris Brezillon destroy_workqueue(master->wq);
5813a379bbcSBoris Brezillon
5823a379bbcSBoris Brezillon WARN_ON(!list_empty(&bus->devs.i2c) || !list_empty(&bus->devs.i3c));
5833a379bbcSBoris Brezillon i3c_bus_cleanup(bus);
5843a379bbcSBoris Brezillon
5853a379bbcSBoris Brezillon of_node_put(dev->of_node);
5863a379bbcSBoris Brezillon }
5873a379bbcSBoris Brezillon
5883a379bbcSBoris Brezillon static const struct device_type i3c_masterdev_type = {
5893a379bbcSBoris Brezillon .groups = i3c_masterdev_groups,
5903a379bbcSBoris Brezillon };
5913a379bbcSBoris Brezillon
i3c_bus_set_mode(struct i3c_bus * i3cbus,enum i3c_bus_mode mode,unsigned long max_i2c_scl_rate)592026d8450SBenjamin Gaignard static int i3c_bus_set_mode(struct i3c_bus *i3cbus, enum i3c_bus_mode mode,
593ecc8fb54SVitor Soares unsigned long max_i2c_scl_rate)
5943a379bbcSBoris Brezillon {
595ecc8fb54SVitor Soares struct i3c_master_controller *master = i3c_bus_to_i3c_master(i3cbus);
596ecc8fb54SVitor Soares
5973a379bbcSBoris Brezillon i3cbus->mode = mode;
5983a379bbcSBoris Brezillon
599ecc8fb54SVitor Soares switch (i3cbus->mode) {
600ecc8fb54SVitor Soares case I3C_BUS_MODE_PURE:
6013a379bbcSBoris Brezillon if (!i3cbus->scl_rate.i3c)
6023a379bbcSBoris Brezillon i3cbus->scl_rate.i3c = I3C_BUS_TYP_I3C_SCL_RATE;
603ecc8fb54SVitor Soares break;
604ecc8fb54SVitor Soares case I3C_BUS_MODE_MIXED_FAST:
605cbf4f732SVitor Soares case I3C_BUS_MODE_MIXED_LIMITED:
606ecc8fb54SVitor Soares if (!i3cbus->scl_rate.i3c)
607ecc8fb54SVitor Soares i3cbus->scl_rate.i3c = I3C_BUS_TYP_I3C_SCL_RATE;
608ecc8fb54SVitor Soares if (!i3cbus->scl_rate.i2c)
609ecc8fb54SVitor Soares i3cbus->scl_rate.i2c = max_i2c_scl_rate;
610ecc8fb54SVitor Soares break;
611ecc8fb54SVitor Soares case I3C_BUS_MODE_MIXED_SLOW:
612ecc8fb54SVitor Soares if (!i3cbus->scl_rate.i2c)
613ecc8fb54SVitor Soares i3cbus->scl_rate.i2c = max_i2c_scl_rate;
614ecc8fb54SVitor Soares if (!i3cbus->scl_rate.i3c ||
615ecc8fb54SVitor Soares i3cbus->scl_rate.i3c > i3cbus->scl_rate.i2c)
616ecc8fb54SVitor Soares i3cbus->scl_rate.i3c = i3cbus->scl_rate.i2c;
617ecc8fb54SVitor Soares break;
618ecc8fb54SVitor Soares default:
619ecc8fb54SVitor Soares return -EINVAL;
6203a379bbcSBoris Brezillon }
6213a379bbcSBoris Brezillon
622ecc8fb54SVitor Soares dev_dbg(&master->dev, "i2c-scl = %ld Hz i3c-scl = %ld Hz\n",
623ecc8fb54SVitor Soares i3cbus->scl_rate.i2c, i3cbus->scl_rate.i3c);
624ecc8fb54SVitor Soares
6253a379bbcSBoris Brezillon /*
6263a379bbcSBoris Brezillon * I3C/I2C frequency may have been overridden, check that user-provided
6273a379bbcSBoris Brezillon * values are not exceeding max possible frequency.
6283a379bbcSBoris Brezillon */
6293a379bbcSBoris Brezillon if (i3cbus->scl_rate.i3c > I3C_BUS_MAX_I3C_SCL_RATE ||
6303a379bbcSBoris Brezillon i3cbus->scl_rate.i2c > I3C_BUS_I2C_FM_PLUS_SCL_RATE)
6313a379bbcSBoris Brezillon return -EINVAL;
6323a379bbcSBoris Brezillon
6333a379bbcSBoris Brezillon return 0;
6343a379bbcSBoris Brezillon }
6353a379bbcSBoris Brezillon
6363a379bbcSBoris Brezillon static struct i3c_master_controller *
i2c_adapter_to_i3c_master(struct i2c_adapter * adap)6373a379bbcSBoris Brezillon i2c_adapter_to_i3c_master(struct i2c_adapter *adap)
6383a379bbcSBoris Brezillon {
6393a379bbcSBoris Brezillon return container_of(adap, struct i3c_master_controller, i2c);
6403a379bbcSBoris Brezillon }
6413a379bbcSBoris Brezillon
6423a379bbcSBoris Brezillon static struct i2c_adapter *
i3c_master_to_i2c_adapter(struct i3c_master_controller * master)6433a379bbcSBoris Brezillon i3c_master_to_i2c_adapter(struct i3c_master_controller *master)
6443a379bbcSBoris Brezillon {
6453a379bbcSBoris Brezillon return &master->i2c;
6463a379bbcSBoris Brezillon }
6473a379bbcSBoris Brezillon
i3c_master_free_i2c_dev(struct i2c_dev_desc * dev)6483a379bbcSBoris Brezillon static void i3c_master_free_i2c_dev(struct i2c_dev_desc *dev)
6493a379bbcSBoris Brezillon {
6503a379bbcSBoris Brezillon kfree(dev);
6513a379bbcSBoris Brezillon }
6523a379bbcSBoris Brezillon
6533a379bbcSBoris Brezillon static struct i2c_dev_desc *
i3c_master_alloc_i2c_dev(struct i3c_master_controller * master,u16 addr,u8 lvr)6543a379bbcSBoris Brezillon i3c_master_alloc_i2c_dev(struct i3c_master_controller *master,
65531b9887cSJamie Iles u16 addr, u8 lvr)
6563a379bbcSBoris Brezillon {
6573a379bbcSBoris Brezillon struct i2c_dev_desc *dev;
6583a379bbcSBoris Brezillon
6593a379bbcSBoris Brezillon dev = kzalloc(sizeof(*dev), GFP_KERNEL);
6603a379bbcSBoris Brezillon if (!dev)
6613a379bbcSBoris Brezillon return ERR_PTR(-ENOMEM);
6623a379bbcSBoris Brezillon
6633a379bbcSBoris Brezillon dev->common.master = master;
66431b9887cSJamie Iles dev->addr = addr;
66531b9887cSJamie Iles dev->lvr = lvr;
6663a379bbcSBoris Brezillon
6673a379bbcSBoris Brezillon return dev;
6683a379bbcSBoris Brezillon }
6693a379bbcSBoris Brezillon
i3c_ccc_cmd_dest_init(struct i3c_ccc_cmd_dest * dest,u8 addr,u16 payloadlen)6703a379bbcSBoris Brezillon static void *i3c_ccc_cmd_dest_init(struct i3c_ccc_cmd_dest *dest, u8 addr,
6713a379bbcSBoris Brezillon u16 payloadlen)
6723a379bbcSBoris Brezillon {
6733a379bbcSBoris Brezillon dest->addr = addr;
6743a379bbcSBoris Brezillon dest->payload.len = payloadlen;
6753a379bbcSBoris Brezillon if (payloadlen)
6763a379bbcSBoris Brezillon dest->payload.data = kzalloc(payloadlen, GFP_KERNEL);
6773a379bbcSBoris Brezillon else
6783a379bbcSBoris Brezillon dest->payload.data = NULL;
6793a379bbcSBoris Brezillon
6803a379bbcSBoris Brezillon return dest->payload.data;
6813a379bbcSBoris Brezillon }
6823a379bbcSBoris Brezillon
i3c_ccc_cmd_dest_cleanup(struct i3c_ccc_cmd_dest * dest)6833a379bbcSBoris Brezillon static void i3c_ccc_cmd_dest_cleanup(struct i3c_ccc_cmd_dest *dest)
6843a379bbcSBoris Brezillon {
6853a379bbcSBoris Brezillon kfree(dest->payload.data);
6863a379bbcSBoris Brezillon }
6873a379bbcSBoris Brezillon
i3c_ccc_cmd_init(struct i3c_ccc_cmd * cmd,bool rnw,u8 id,struct i3c_ccc_cmd_dest * dests,unsigned int ndests)6883a379bbcSBoris Brezillon static void i3c_ccc_cmd_init(struct i3c_ccc_cmd *cmd, bool rnw, u8 id,
6893a379bbcSBoris Brezillon struct i3c_ccc_cmd_dest *dests,
6903a379bbcSBoris Brezillon unsigned int ndests)
6913a379bbcSBoris Brezillon {
6923a379bbcSBoris Brezillon cmd->rnw = rnw ? 1 : 0;
6933a379bbcSBoris Brezillon cmd->id = id;
6943a379bbcSBoris Brezillon cmd->dests = dests;
6953a379bbcSBoris Brezillon cmd->ndests = ndests;
6963a379bbcSBoris Brezillon cmd->err = I3C_ERROR_UNKNOWN;
6973a379bbcSBoris Brezillon }
6983a379bbcSBoris Brezillon
i3c_master_send_ccc_cmd_locked(struct i3c_master_controller * master,struct i3c_ccc_cmd * cmd)6993a379bbcSBoris Brezillon static int i3c_master_send_ccc_cmd_locked(struct i3c_master_controller *master,
7003a379bbcSBoris Brezillon struct i3c_ccc_cmd *cmd)
7013a379bbcSBoris Brezillon {
7023a379bbcSBoris Brezillon int ret;
7033a379bbcSBoris Brezillon
7043a379bbcSBoris Brezillon if (!cmd || !master)
7053a379bbcSBoris Brezillon return -EINVAL;
7063a379bbcSBoris Brezillon
7073a379bbcSBoris Brezillon if (WARN_ON(master->init_done &&
7083a379bbcSBoris Brezillon !rwsem_is_locked(&master->bus.lock)))
7093a379bbcSBoris Brezillon return -EINVAL;
7103a379bbcSBoris Brezillon
7113a379bbcSBoris Brezillon if (!master->ops->send_ccc_cmd)
7123a379bbcSBoris Brezillon return -ENOTSUPP;
7133a379bbcSBoris Brezillon
7143a379bbcSBoris Brezillon if ((cmd->id & I3C_CCC_DIRECT) && (!cmd->dests || !cmd->ndests))
7153a379bbcSBoris Brezillon return -EINVAL;
7163a379bbcSBoris Brezillon
7173a379bbcSBoris Brezillon if (master->ops->supports_ccc_cmd &&
7183a379bbcSBoris Brezillon !master->ops->supports_ccc_cmd(master, cmd))
7193a379bbcSBoris Brezillon return -ENOTSUPP;
7203a379bbcSBoris Brezillon
7213a379bbcSBoris Brezillon ret = master->ops->send_ccc_cmd(master, cmd);
7223a379bbcSBoris Brezillon if (ret) {
7233a379bbcSBoris Brezillon if (cmd->err != I3C_ERROR_UNKNOWN)
7243a379bbcSBoris Brezillon return cmd->err;
7253a379bbcSBoris Brezillon
7263a379bbcSBoris Brezillon return ret;
7273a379bbcSBoris Brezillon }
7283a379bbcSBoris Brezillon
7293a379bbcSBoris Brezillon return 0;
7303a379bbcSBoris Brezillon }
7313a379bbcSBoris Brezillon
7323a379bbcSBoris Brezillon static struct i2c_dev_desc *
i3c_master_find_i2c_dev_by_addr(const struct i3c_master_controller * master,u16 addr)7333a379bbcSBoris Brezillon i3c_master_find_i2c_dev_by_addr(const struct i3c_master_controller *master,
7343a379bbcSBoris Brezillon u16 addr)
7353a379bbcSBoris Brezillon {
7363a379bbcSBoris Brezillon struct i2c_dev_desc *dev;
7373a379bbcSBoris Brezillon
7383a379bbcSBoris Brezillon i3c_bus_for_each_i2cdev(&master->bus, dev) {
73931b9887cSJamie Iles if (dev->addr == addr)
7403a379bbcSBoris Brezillon return dev;
7413a379bbcSBoris Brezillon }
7423a379bbcSBoris Brezillon
7433a379bbcSBoris Brezillon return NULL;
7443a379bbcSBoris Brezillon }
7453a379bbcSBoris Brezillon
7463a379bbcSBoris Brezillon /**
7473a379bbcSBoris Brezillon * i3c_master_get_free_addr() - get a free address on the bus
7483a379bbcSBoris Brezillon * @master: I3C master object
7493a379bbcSBoris Brezillon * @start_addr: where to start searching
7503a379bbcSBoris Brezillon *
7513a379bbcSBoris Brezillon * This function must be called with the bus lock held in write mode.
7523a379bbcSBoris Brezillon *
7533a379bbcSBoris Brezillon * Return: the first free address starting at @start_addr (included) or -ENOMEM
7543a379bbcSBoris Brezillon * if there's no more address available.
7553a379bbcSBoris Brezillon */
i3c_master_get_free_addr(struct i3c_master_controller * master,u8 start_addr)7563a379bbcSBoris Brezillon int i3c_master_get_free_addr(struct i3c_master_controller *master,
7573a379bbcSBoris Brezillon u8 start_addr)
7583a379bbcSBoris Brezillon {
7593a379bbcSBoris Brezillon return i3c_bus_get_free_addr(&master->bus, start_addr);
7603a379bbcSBoris Brezillon }
7613a379bbcSBoris Brezillon EXPORT_SYMBOL_GPL(i3c_master_get_free_addr);
7623a379bbcSBoris Brezillon
i3c_device_release(struct device * dev)7633a379bbcSBoris Brezillon static void i3c_device_release(struct device *dev)
7643a379bbcSBoris Brezillon {
7653a379bbcSBoris Brezillon struct i3c_device *i3cdev = dev_to_i3cdev(dev);
7663a379bbcSBoris Brezillon
7673a379bbcSBoris Brezillon WARN_ON(i3cdev->desc);
7683a379bbcSBoris Brezillon
7693a379bbcSBoris Brezillon of_node_put(i3cdev->dev.of_node);
7703a379bbcSBoris Brezillon kfree(i3cdev);
7713a379bbcSBoris Brezillon }
7723a379bbcSBoris Brezillon
i3c_master_free_i3c_dev(struct i3c_dev_desc * dev)7733a379bbcSBoris Brezillon static void i3c_master_free_i3c_dev(struct i3c_dev_desc *dev)
7743a379bbcSBoris Brezillon {
7753a379bbcSBoris Brezillon kfree(dev);
7763a379bbcSBoris Brezillon }
7773a379bbcSBoris Brezillon
7783a379bbcSBoris Brezillon static struct i3c_dev_desc *
i3c_master_alloc_i3c_dev(struct i3c_master_controller * master,const struct i3c_device_info * info)7793a379bbcSBoris Brezillon i3c_master_alloc_i3c_dev(struct i3c_master_controller *master,
7803a379bbcSBoris Brezillon const struct i3c_device_info *info)
7813a379bbcSBoris Brezillon {
7823a379bbcSBoris Brezillon struct i3c_dev_desc *dev;
7833a379bbcSBoris Brezillon
7843a379bbcSBoris Brezillon dev = kzalloc(sizeof(*dev), GFP_KERNEL);
7853a379bbcSBoris Brezillon if (!dev)
7863a379bbcSBoris Brezillon return ERR_PTR(-ENOMEM);
7873a379bbcSBoris Brezillon
7883a379bbcSBoris Brezillon dev->common.master = master;
7893a379bbcSBoris Brezillon dev->info = *info;
7903a379bbcSBoris Brezillon mutex_init(&dev->ibi_lock);
7913a379bbcSBoris Brezillon
7923a379bbcSBoris Brezillon return dev;
7933a379bbcSBoris Brezillon }
7943a379bbcSBoris Brezillon
i3c_master_rstdaa_locked(struct i3c_master_controller * master,u8 addr)7953a379bbcSBoris Brezillon static int i3c_master_rstdaa_locked(struct i3c_master_controller *master,
7963a379bbcSBoris Brezillon u8 addr)
7973a379bbcSBoris Brezillon {
7983a379bbcSBoris Brezillon enum i3c_addr_slot_status addrstat;
7993a379bbcSBoris Brezillon struct i3c_ccc_cmd_dest dest;
8003a379bbcSBoris Brezillon struct i3c_ccc_cmd cmd;
8013a379bbcSBoris Brezillon int ret;
8023a379bbcSBoris Brezillon
8033a379bbcSBoris Brezillon if (!master)
8043a379bbcSBoris Brezillon return -EINVAL;
8053a379bbcSBoris Brezillon
8063a379bbcSBoris Brezillon addrstat = i3c_bus_get_addr_slot_status(&master->bus, addr);
8073a379bbcSBoris Brezillon if (addr != I3C_BROADCAST_ADDR && addrstat != I3C_ADDR_SLOT_I3C_DEV)
8083a379bbcSBoris Brezillon return -EINVAL;
8093a379bbcSBoris Brezillon
8103a379bbcSBoris Brezillon i3c_ccc_cmd_dest_init(&dest, addr, 0);
8113a379bbcSBoris Brezillon i3c_ccc_cmd_init(&cmd, false,
8123a379bbcSBoris Brezillon I3C_CCC_RSTDAA(addr == I3C_BROADCAST_ADDR),
8133a379bbcSBoris Brezillon &dest, 1);
8143a379bbcSBoris Brezillon ret = i3c_master_send_ccc_cmd_locked(master, &cmd);
8153a379bbcSBoris Brezillon i3c_ccc_cmd_dest_cleanup(&dest);
8163a379bbcSBoris Brezillon
8173a379bbcSBoris Brezillon return ret;
8183a379bbcSBoris Brezillon }
8193a379bbcSBoris Brezillon
8203a379bbcSBoris Brezillon /**
8213a379bbcSBoris Brezillon * i3c_master_entdaa_locked() - start a DAA (Dynamic Address Assignment)
8223a379bbcSBoris Brezillon * procedure
8233a379bbcSBoris Brezillon * @master: master used to send frames on the bus
8243a379bbcSBoris Brezillon *
8253a379bbcSBoris Brezillon * Send a ENTDAA CCC command to start a DAA procedure.
8263a379bbcSBoris Brezillon *
8273a379bbcSBoris Brezillon * Note that this function only sends the ENTDAA CCC command, all the logic
8283a379bbcSBoris Brezillon * behind dynamic address assignment has to be handled in the I3C master
8293a379bbcSBoris Brezillon * driver.
8303a379bbcSBoris Brezillon *
8313a379bbcSBoris Brezillon * This function must be called with the bus lock held in write mode.
8323a379bbcSBoris Brezillon *
8333a379bbcSBoris Brezillon * Return: 0 in case of success, a positive I3C error code if the error is
8343a379bbcSBoris Brezillon * one of the official Mx error codes, and a negative error code otherwise.
8353a379bbcSBoris Brezillon */
i3c_master_entdaa_locked(struct i3c_master_controller * master)8363a379bbcSBoris Brezillon int i3c_master_entdaa_locked(struct i3c_master_controller *master)
8373a379bbcSBoris Brezillon {
8383a379bbcSBoris Brezillon struct i3c_ccc_cmd_dest dest;
8393a379bbcSBoris Brezillon struct i3c_ccc_cmd cmd;
8403a379bbcSBoris Brezillon int ret;
8413a379bbcSBoris Brezillon
8423a379bbcSBoris Brezillon i3c_ccc_cmd_dest_init(&dest, I3C_BROADCAST_ADDR, 0);
8433a379bbcSBoris Brezillon i3c_ccc_cmd_init(&cmd, false, I3C_CCC_ENTDAA, &dest, 1);
8443a379bbcSBoris Brezillon ret = i3c_master_send_ccc_cmd_locked(master, &cmd);
8453a379bbcSBoris Brezillon i3c_ccc_cmd_dest_cleanup(&dest);
8463a379bbcSBoris Brezillon
8473a379bbcSBoris Brezillon return ret;
8483a379bbcSBoris Brezillon }
8493a379bbcSBoris Brezillon EXPORT_SYMBOL_GPL(i3c_master_entdaa_locked);
8503a379bbcSBoris Brezillon
i3c_master_enec_disec_locked(struct i3c_master_controller * master,u8 addr,bool enable,u8 evts)8513a379bbcSBoris Brezillon static int i3c_master_enec_disec_locked(struct i3c_master_controller *master,
8523a379bbcSBoris Brezillon u8 addr, bool enable, u8 evts)
8533a379bbcSBoris Brezillon {
8543a379bbcSBoris Brezillon struct i3c_ccc_events *events;
8553a379bbcSBoris Brezillon struct i3c_ccc_cmd_dest dest;
8563a379bbcSBoris Brezillon struct i3c_ccc_cmd cmd;
8573a379bbcSBoris Brezillon int ret;
8583a379bbcSBoris Brezillon
8593a379bbcSBoris Brezillon events = i3c_ccc_cmd_dest_init(&dest, addr, sizeof(*events));
8603a379bbcSBoris Brezillon if (!events)
8613a379bbcSBoris Brezillon return -ENOMEM;
8623a379bbcSBoris Brezillon
8633a379bbcSBoris Brezillon events->events = evts;
8643a379bbcSBoris Brezillon i3c_ccc_cmd_init(&cmd, false,
8653a379bbcSBoris Brezillon enable ?
8663a379bbcSBoris Brezillon I3C_CCC_ENEC(addr == I3C_BROADCAST_ADDR) :
8673a379bbcSBoris Brezillon I3C_CCC_DISEC(addr == I3C_BROADCAST_ADDR),
8683a379bbcSBoris Brezillon &dest, 1);
8693a379bbcSBoris Brezillon ret = i3c_master_send_ccc_cmd_locked(master, &cmd);
8703a379bbcSBoris Brezillon i3c_ccc_cmd_dest_cleanup(&dest);
8713a379bbcSBoris Brezillon
8723a379bbcSBoris Brezillon return ret;
8733a379bbcSBoris Brezillon }
8743a379bbcSBoris Brezillon
8753a379bbcSBoris Brezillon /**
8763a379bbcSBoris Brezillon * i3c_master_disec_locked() - send a DISEC CCC command
8773a379bbcSBoris Brezillon * @master: master used to send frames on the bus
8783a379bbcSBoris Brezillon * @addr: a valid I3C slave address or %I3C_BROADCAST_ADDR
8793a379bbcSBoris Brezillon * @evts: events to disable
8803a379bbcSBoris Brezillon *
8813a379bbcSBoris Brezillon * Send a DISEC CCC command to disable some or all events coming from a
8823a379bbcSBoris Brezillon * specific slave, or all devices if @addr is %I3C_BROADCAST_ADDR.
8833a379bbcSBoris Brezillon *
8843a379bbcSBoris Brezillon * This function must be called with the bus lock held in write mode.
8853a379bbcSBoris Brezillon *
8863a379bbcSBoris Brezillon * Return: 0 in case of success, a positive I3C error code if the error is
8873a379bbcSBoris Brezillon * one of the official Mx error codes, and a negative error code otherwise.
8883a379bbcSBoris Brezillon */
i3c_master_disec_locked(struct i3c_master_controller * master,u8 addr,u8 evts)8893a379bbcSBoris Brezillon int i3c_master_disec_locked(struct i3c_master_controller *master, u8 addr,
8903a379bbcSBoris Brezillon u8 evts)
8913a379bbcSBoris Brezillon {
8923a379bbcSBoris Brezillon return i3c_master_enec_disec_locked(master, addr, false, evts);
8933a379bbcSBoris Brezillon }
8943a379bbcSBoris Brezillon EXPORT_SYMBOL_GPL(i3c_master_disec_locked);
8953a379bbcSBoris Brezillon
8963a379bbcSBoris Brezillon /**
8973a379bbcSBoris Brezillon * i3c_master_enec_locked() - send an ENEC CCC command
8983a379bbcSBoris Brezillon * @master: master used to send frames on the bus
8993a379bbcSBoris Brezillon * @addr: a valid I3C slave address or %I3C_BROADCAST_ADDR
9003a379bbcSBoris Brezillon * @evts: events to disable
9013a379bbcSBoris Brezillon *
9023a379bbcSBoris Brezillon * Sends an ENEC CCC command to enable some or all events coming from a
9033a379bbcSBoris Brezillon * specific slave, or all devices if @addr is %I3C_BROADCAST_ADDR.
9043a379bbcSBoris Brezillon *
9053a379bbcSBoris Brezillon * This function must be called with the bus lock held in write mode.
9063a379bbcSBoris Brezillon *
9073a379bbcSBoris Brezillon * Return: 0 in case of success, a positive I3C error code if the error is
9083a379bbcSBoris Brezillon * one of the official Mx error codes, and a negative error code otherwise.
9093a379bbcSBoris Brezillon */
i3c_master_enec_locked(struct i3c_master_controller * master,u8 addr,u8 evts)9103a379bbcSBoris Brezillon int i3c_master_enec_locked(struct i3c_master_controller *master, u8 addr,
9113a379bbcSBoris Brezillon u8 evts)
9123a379bbcSBoris Brezillon {
9133a379bbcSBoris Brezillon return i3c_master_enec_disec_locked(master, addr, true, evts);
9143a379bbcSBoris Brezillon }
9153a379bbcSBoris Brezillon EXPORT_SYMBOL_GPL(i3c_master_enec_locked);
9163a379bbcSBoris Brezillon
9173a379bbcSBoris Brezillon /**
9183a379bbcSBoris Brezillon * i3c_master_defslvs_locked() - send a DEFSLVS CCC command
9193a379bbcSBoris Brezillon * @master: master used to send frames on the bus
9203a379bbcSBoris Brezillon *
9213a379bbcSBoris Brezillon * Send a DEFSLVS CCC command containing all the devices known to the @master.
9223a379bbcSBoris Brezillon * This is useful when you have secondary masters on the bus to propagate
9233a379bbcSBoris Brezillon * device information.
9243a379bbcSBoris Brezillon *
9253a379bbcSBoris Brezillon * This should be called after all I3C devices have been discovered (in other
9263a379bbcSBoris Brezillon * words, after the DAA procedure has finished) and instantiated in
9273a379bbcSBoris Brezillon * &i3c_master_controller_ops->bus_init().
9283a379bbcSBoris Brezillon * It should also be called if a master ACKed an Hot-Join request and assigned
9293a379bbcSBoris Brezillon * a dynamic address to the device joining the bus.
9303a379bbcSBoris Brezillon *
9313a379bbcSBoris Brezillon * This function must be called with the bus lock held in write mode.
9323a379bbcSBoris Brezillon *
9333a379bbcSBoris Brezillon * Return: 0 in case of success, a positive I3C error code if the error is
9343a379bbcSBoris Brezillon * one of the official Mx error codes, and a negative error code otherwise.
9353a379bbcSBoris Brezillon */
i3c_master_defslvs_locked(struct i3c_master_controller * master)9363a379bbcSBoris Brezillon int i3c_master_defslvs_locked(struct i3c_master_controller *master)
9373a379bbcSBoris Brezillon {
9383a379bbcSBoris Brezillon struct i3c_ccc_defslvs *defslvs;
9393a379bbcSBoris Brezillon struct i3c_ccc_dev_desc *desc;
9403a379bbcSBoris Brezillon struct i3c_ccc_cmd_dest dest;
9413a379bbcSBoris Brezillon struct i3c_dev_desc *i3cdev;
9423a379bbcSBoris Brezillon struct i2c_dev_desc *i2cdev;
9433a379bbcSBoris Brezillon struct i3c_ccc_cmd cmd;
9443a379bbcSBoris Brezillon struct i3c_bus *bus;
9453a379bbcSBoris Brezillon bool send = false;
9463a379bbcSBoris Brezillon int ndevs = 0, ret;
9473a379bbcSBoris Brezillon
9483a379bbcSBoris Brezillon if (!master)
9493a379bbcSBoris Brezillon return -EINVAL;
9503a379bbcSBoris Brezillon
9513a379bbcSBoris Brezillon bus = i3c_master_get_bus(master);
9523a379bbcSBoris Brezillon i3c_bus_for_each_i3cdev(bus, i3cdev) {
9533a379bbcSBoris Brezillon ndevs++;
9543a379bbcSBoris Brezillon
9553a379bbcSBoris Brezillon if (i3cdev == master->this)
9563a379bbcSBoris Brezillon continue;
9573a379bbcSBoris Brezillon
9583a379bbcSBoris Brezillon if (I3C_BCR_DEVICE_ROLE(i3cdev->info.bcr) ==
9593a379bbcSBoris Brezillon I3C_BCR_I3C_MASTER)
9603a379bbcSBoris Brezillon send = true;
9613a379bbcSBoris Brezillon }
9623a379bbcSBoris Brezillon
9633a379bbcSBoris Brezillon /* No other master on the bus, skip DEFSLVS. */
9643a379bbcSBoris Brezillon if (!send)
9653a379bbcSBoris Brezillon return 0;
9663a379bbcSBoris Brezillon
9673a379bbcSBoris Brezillon i3c_bus_for_each_i2cdev(bus, i2cdev)
9683a379bbcSBoris Brezillon ndevs++;
9693a379bbcSBoris Brezillon
9703a379bbcSBoris Brezillon defslvs = i3c_ccc_cmd_dest_init(&dest, I3C_BROADCAST_ADDR,
971ede20015SGustavo A. R. Silva struct_size(defslvs, slaves,
972ede20015SGustavo A. R. Silva ndevs - 1));
9733a379bbcSBoris Brezillon if (!defslvs)
9743a379bbcSBoris Brezillon return -ENOMEM;
9753a379bbcSBoris Brezillon
9763a379bbcSBoris Brezillon defslvs->count = ndevs;
9773a379bbcSBoris Brezillon defslvs->master.bcr = master->this->info.bcr;
9783a379bbcSBoris Brezillon defslvs->master.dcr = master->this->info.dcr;
9793a379bbcSBoris Brezillon defslvs->master.dyn_addr = master->this->info.dyn_addr << 1;
9803a379bbcSBoris Brezillon defslvs->master.static_addr = I3C_BROADCAST_ADDR << 1;
9813a379bbcSBoris Brezillon
9823a379bbcSBoris Brezillon desc = defslvs->slaves;
9833a379bbcSBoris Brezillon i3c_bus_for_each_i2cdev(bus, i2cdev) {
984b1ac3a4bSPrzemyslaw Gaj desc->lvr = i2cdev->lvr;
985b1ac3a4bSPrzemyslaw Gaj desc->static_addr = i2cdev->addr << 1;
9863a379bbcSBoris Brezillon desc++;
9873a379bbcSBoris Brezillon }
9883a379bbcSBoris Brezillon
9893a379bbcSBoris Brezillon i3c_bus_for_each_i3cdev(bus, i3cdev) {
9903a379bbcSBoris Brezillon /* Skip the I3C dev representing this master. */
9913a379bbcSBoris Brezillon if (i3cdev == master->this)
9923a379bbcSBoris Brezillon continue;
9933a379bbcSBoris Brezillon
9943a379bbcSBoris Brezillon desc->bcr = i3cdev->info.bcr;
9953a379bbcSBoris Brezillon desc->dcr = i3cdev->info.dcr;
9963a379bbcSBoris Brezillon desc->dyn_addr = i3cdev->info.dyn_addr << 1;
9973a379bbcSBoris Brezillon desc->static_addr = i3cdev->info.static_addr << 1;
9983a379bbcSBoris Brezillon desc++;
9993a379bbcSBoris Brezillon }
10003a379bbcSBoris Brezillon
10013a379bbcSBoris Brezillon i3c_ccc_cmd_init(&cmd, false, I3C_CCC_DEFSLVS, &dest, 1);
10023a379bbcSBoris Brezillon ret = i3c_master_send_ccc_cmd_locked(master, &cmd);
10033a379bbcSBoris Brezillon i3c_ccc_cmd_dest_cleanup(&dest);
10043a379bbcSBoris Brezillon
10053a379bbcSBoris Brezillon return ret;
10063a379bbcSBoris Brezillon }
10073a379bbcSBoris Brezillon EXPORT_SYMBOL_GPL(i3c_master_defslvs_locked);
10083a379bbcSBoris Brezillon
i3c_master_setda_locked(struct i3c_master_controller * master,u8 oldaddr,u8 newaddr,bool setdasa)10093a379bbcSBoris Brezillon static int i3c_master_setda_locked(struct i3c_master_controller *master,
10103a379bbcSBoris Brezillon u8 oldaddr, u8 newaddr, bool setdasa)
10113a379bbcSBoris Brezillon {
10123a379bbcSBoris Brezillon struct i3c_ccc_cmd_dest dest;
10133a379bbcSBoris Brezillon struct i3c_ccc_setda *setda;
10143a379bbcSBoris Brezillon struct i3c_ccc_cmd cmd;
10153a379bbcSBoris Brezillon int ret;
10163a379bbcSBoris Brezillon
10173a379bbcSBoris Brezillon if (!oldaddr || !newaddr)
10183a379bbcSBoris Brezillon return -EINVAL;
10193a379bbcSBoris Brezillon
10203a379bbcSBoris Brezillon setda = i3c_ccc_cmd_dest_init(&dest, oldaddr, sizeof(*setda));
10213a379bbcSBoris Brezillon if (!setda)
10223a379bbcSBoris Brezillon return -ENOMEM;
10233a379bbcSBoris Brezillon
10243a379bbcSBoris Brezillon setda->addr = newaddr << 1;
10253a379bbcSBoris Brezillon i3c_ccc_cmd_init(&cmd, false,
10263a379bbcSBoris Brezillon setdasa ? I3C_CCC_SETDASA : I3C_CCC_SETNEWDA,
10273a379bbcSBoris Brezillon &dest, 1);
10283a379bbcSBoris Brezillon ret = i3c_master_send_ccc_cmd_locked(master, &cmd);
10293a379bbcSBoris Brezillon i3c_ccc_cmd_dest_cleanup(&dest);
10303a379bbcSBoris Brezillon
10313a379bbcSBoris Brezillon return ret;
10323a379bbcSBoris Brezillon }
10333a379bbcSBoris Brezillon
i3c_master_setdasa_locked(struct i3c_master_controller * master,u8 static_addr,u8 dyn_addr)10343a379bbcSBoris Brezillon static int i3c_master_setdasa_locked(struct i3c_master_controller *master,
10353a379bbcSBoris Brezillon u8 static_addr, u8 dyn_addr)
10363a379bbcSBoris Brezillon {
10373a379bbcSBoris Brezillon return i3c_master_setda_locked(master, static_addr, dyn_addr, true);
10383a379bbcSBoris Brezillon }
10393a379bbcSBoris Brezillon
i3c_master_setnewda_locked(struct i3c_master_controller * master,u8 oldaddr,u8 newaddr)10403a379bbcSBoris Brezillon static int i3c_master_setnewda_locked(struct i3c_master_controller *master,
10413a379bbcSBoris Brezillon u8 oldaddr, u8 newaddr)
10423a379bbcSBoris Brezillon {
10433a379bbcSBoris Brezillon return i3c_master_setda_locked(master, oldaddr, newaddr, false);
10443a379bbcSBoris Brezillon }
10453a379bbcSBoris Brezillon
i3c_master_getmrl_locked(struct i3c_master_controller * master,struct i3c_device_info * info)10463a379bbcSBoris Brezillon static int i3c_master_getmrl_locked(struct i3c_master_controller *master,
10473a379bbcSBoris Brezillon struct i3c_device_info *info)
10483a379bbcSBoris Brezillon {
10493a379bbcSBoris Brezillon struct i3c_ccc_cmd_dest dest;
10503a379bbcSBoris Brezillon struct i3c_ccc_mrl *mrl;
10513a379bbcSBoris Brezillon struct i3c_ccc_cmd cmd;
10523a379bbcSBoris Brezillon int ret;
10533a379bbcSBoris Brezillon
10543a379bbcSBoris Brezillon mrl = i3c_ccc_cmd_dest_init(&dest, info->dyn_addr, sizeof(*mrl));
10553a379bbcSBoris Brezillon if (!mrl)
10563a379bbcSBoris Brezillon return -ENOMEM;
10573a379bbcSBoris Brezillon
10583a379bbcSBoris Brezillon /*
10593a379bbcSBoris Brezillon * When the device does not have IBI payload GETMRL only returns 2
10603a379bbcSBoris Brezillon * bytes of data.
10613a379bbcSBoris Brezillon */
10623a379bbcSBoris Brezillon if (!(info->bcr & I3C_BCR_IBI_PAYLOAD))
10633a379bbcSBoris Brezillon dest.payload.len -= 1;
10643a379bbcSBoris Brezillon
10653a379bbcSBoris Brezillon i3c_ccc_cmd_init(&cmd, true, I3C_CCC_GETMRL, &dest, 1);
10663a379bbcSBoris Brezillon ret = i3c_master_send_ccc_cmd_locked(master, &cmd);
10673a379bbcSBoris Brezillon if (ret)
10683a379bbcSBoris Brezillon goto out;
10693a379bbcSBoris Brezillon
1070b4203ce0SNicolas Pitre switch (dest.payload.len) {
1071b4203ce0SNicolas Pitre case 3:
1072b4203ce0SNicolas Pitre info->max_ibi_len = mrl->ibi_len;
1073b4203ce0SNicolas Pitre fallthrough;
1074b4203ce0SNicolas Pitre case 2:
1075b4203ce0SNicolas Pitre info->max_read_len = be16_to_cpu(mrl->read_len);
1076b4203ce0SNicolas Pitre break;
1077b4203ce0SNicolas Pitre default:
10783a379bbcSBoris Brezillon ret = -EIO;
10793a379bbcSBoris Brezillon goto out;
10803a379bbcSBoris Brezillon }
10813a379bbcSBoris Brezillon
10823a379bbcSBoris Brezillon out:
10833a379bbcSBoris Brezillon i3c_ccc_cmd_dest_cleanup(&dest);
10843a379bbcSBoris Brezillon
10853a379bbcSBoris Brezillon return ret;
10863a379bbcSBoris Brezillon }
10873a379bbcSBoris Brezillon
i3c_master_getmwl_locked(struct i3c_master_controller * master,struct i3c_device_info * info)10883a379bbcSBoris Brezillon static int i3c_master_getmwl_locked(struct i3c_master_controller *master,
10893a379bbcSBoris Brezillon struct i3c_device_info *info)
10903a379bbcSBoris Brezillon {
10913a379bbcSBoris Brezillon struct i3c_ccc_cmd_dest dest;
10923a379bbcSBoris Brezillon struct i3c_ccc_mwl *mwl;
10933a379bbcSBoris Brezillon struct i3c_ccc_cmd cmd;
10943a379bbcSBoris Brezillon int ret;
10953a379bbcSBoris Brezillon
10963a379bbcSBoris Brezillon mwl = i3c_ccc_cmd_dest_init(&dest, info->dyn_addr, sizeof(*mwl));
10973a379bbcSBoris Brezillon if (!mwl)
10983a379bbcSBoris Brezillon return -ENOMEM;
10993a379bbcSBoris Brezillon
11003a379bbcSBoris Brezillon i3c_ccc_cmd_init(&cmd, true, I3C_CCC_GETMWL, &dest, 1);
11013a379bbcSBoris Brezillon ret = i3c_master_send_ccc_cmd_locked(master, &cmd);
11023a379bbcSBoris Brezillon if (ret)
11033a379bbcSBoris Brezillon goto out;
11043a379bbcSBoris Brezillon
11057afe9a4eSWenwen Wang if (dest.payload.len != sizeof(*mwl)) {
11067afe9a4eSWenwen Wang ret = -EIO;
11077afe9a4eSWenwen Wang goto out;
11087afe9a4eSWenwen Wang }
11093a379bbcSBoris Brezillon
11103a379bbcSBoris Brezillon info->max_write_len = be16_to_cpu(mwl->len);
11113a379bbcSBoris Brezillon
11123a379bbcSBoris Brezillon out:
11133a379bbcSBoris Brezillon i3c_ccc_cmd_dest_cleanup(&dest);
11143a379bbcSBoris Brezillon
11153a379bbcSBoris Brezillon return ret;
11163a379bbcSBoris Brezillon }
11173a379bbcSBoris Brezillon
i3c_master_getmxds_locked(struct i3c_master_controller * master,struct i3c_device_info * info)11183a379bbcSBoris Brezillon static int i3c_master_getmxds_locked(struct i3c_master_controller *master,
11193a379bbcSBoris Brezillon struct i3c_device_info *info)
11203a379bbcSBoris Brezillon {
11213a379bbcSBoris Brezillon struct i3c_ccc_getmxds *getmaxds;
11223a379bbcSBoris Brezillon struct i3c_ccc_cmd_dest dest;
11233a379bbcSBoris Brezillon struct i3c_ccc_cmd cmd;
11243a379bbcSBoris Brezillon int ret;
11253a379bbcSBoris Brezillon
11263a379bbcSBoris Brezillon getmaxds = i3c_ccc_cmd_dest_init(&dest, info->dyn_addr,
11273a379bbcSBoris Brezillon sizeof(*getmaxds));
11283a379bbcSBoris Brezillon if (!getmaxds)
11293a379bbcSBoris Brezillon return -ENOMEM;
11303a379bbcSBoris Brezillon
11313a379bbcSBoris Brezillon i3c_ccc_cmd_init(&cmd, true, I3C_CCC_GETMXDS, &dest, 1);
11323a379bbcSBoris Brezillon ret = i3c_master_send_ccc_cmd_locked(master, &cmd);
11333a379bbcSBoris Brezillon if (ret)
11343a379bbcSBoris Brezillon goto out;
11353a379bbcSBoris Brezillon
11363a379bbcSBoris Brezillon if (dest.payload.len != 2 && dest.payload.len != 5) {
11373a379bbcSBoris Brezillon ret = -EIO;
11383a379bbcSBoris Brezillon goto out;
11393a379bbcSBoris Brezillon }
11403a379bbcSBoris Brezillon
11413a379bbcSBoris Brezillon info->max_read_ds = getmaxds->maxrd;
11423a379bbcSBoris Brezillon info->max_write_ds = getmaxds->maxwr;
11433a379bbcSBoris Brezillon if (dest.payload.len == 5)
11443a379bbcSBoris Brezillon info->max_read_turnaround = getmaxds->maxrdturn[0] |
11453a379bbcSBoris Brezillon ((u32)getmaxds->maxrdturn[1] << 8) |
11463a379bbcSBoris Brezillon ((u32)getmaxds->maxrdturn[2] << 16);
11473a379bbcSBoris Brezillon
11483a379bbcSBoris Brezillon out:
11493a379bbcSBoris Brezillon i3c_ccc_cmd_dest_cleanup(&dest);
11503a379bbcSBoris Brezillon
11513a379bbcSBoris Brezillon return ret;
11523a379bbcSBoris Brezillon }
11533a379bbcSBoris Brezillon
i3c_master_gethdrcap_locked(struct i3c_master_controller * master,struct i3c_device_info * info)11543a379bbcSBoris Brezillon static int i3c_master_gethdrcap_locked(struct i3c_master_controller *master,
11553a379bbcSBoris Brezillon struct i3c_device_info *info)
11563a379bbcSBoris Brezillon {
11573a379bbcSBoris Brezillon struct i3c_ccc_gethdrcap *gethdrcap;
11583a379bbcSBoris Brezillon struct i3c_ccc_cmd_dest dest;
11593a379bbcSBoris Brezillon struct i3c_ccc_cmd cmd;
11603a379bbcSBoris Brezillon int ret;
11613a379bbcSBoris Brezillon
11623a379bbcSBoris Brezillon gethdrcap = i3c_ccc_cmd_dest_init(&dest, info->dyn_addr,
11633a379bbcSBoris Brezillon sizeof(*gethdrcap));
11643a379bbcSBoris Brezillon if (!gethdrcap)
11653a379bbcSBoris Brezillon return -ENOMEM;
11663a379bbcSBoris Brezillon
11673a379bbcSBoris Brezillon i3c_ccc_cmd_init(&cmd, true, I3C_CCC_GETHDRCAP, &dest, 1);
11683a379bbcSBoris Brezillon ret = i3c_master_send_ccc_cmd_locked(master, &cmd);
11693a379bbcSBoris Brezillon if (ret)
11703a379bbcSBoris Brezillon goto out;
11713a379bbcSBoris Brezillon
11723a379bbcSBoris Brezillon if (dest.payload.len != 1) {
11733a379bbcSBoris Brezillon ret = -EIO;
11743a379bbcSBoris Brezillon goto out;
11753a379bbcSBoris Brezillon }
11763a379bbcSBoris Brezillon
11773a379bbcSBoris Brezillon info->hdr_cap = gethdrcap->modes;
11783a379bbcSBoris Brezillon
11793a379bbcSBoris Brezillon out:
11803a379bbcSBoris Brezillon i3c_ccc_cmd_dest_cleanup(&dest);
11813a379bbcSBoris Brezillon
11823a379bbcSBoris Brezillon return ret;
11833a379bbcSBoris Brezillon }
11843a379bbcSBoris Brezillon
i3c_master_getpid_locked(struct i3c_master_controller * master,struct i3c_device_info * info)11853a379bbcSBoris Brezillon static int i3c_master_getpid_locked(struct i3c_master_controller *master,
11863a379bbcSBoris Brezillon struct i3c_device_info *info)
11873a379bbcSBoris Brezillon {
11883a379bbcSBoris Brezillon struct i3c_ccc_getpid *getpid;
11893a379bbcSBoris Brezillon struct i3c_ccc_cmd_dest dest;
11903a379bbcSBoris Brezillon struct i3c_ccc_cmd cmd;
11913a379bbcSBoris Brezillon int ret, i;
11923a379bbcSBoris Brezillon
11933a379bbcSBoris Brezillon getpid = i3c_ccc_cmd_dest_init(&dest, info->dyn_addr, sizeof(*getpid));
11943a379bbcSBoris Brezillon if (!getpid)
11953a379bbcSBoris Brezillon return -ENOMEM;
11963a379bbcSBoris Brezillon
11973a379bbcSBoris Brezillon i3c_ccc_cmd_init(&cmd, true, I3C_CCC_GETPID, &dest, 1);
11983a379bbcSBoris Brezillon ret = i3c_master_send_ccc_cmd_locked(master, &cmd);
11993a379bbcSBoris Brezillon if (ret)
12003a379bbcSBoris Brezillon goto out;
12013a379bbcSBoris Brezillon
12023a379bbcSBoris Brezillon info->pid = 0;
12033a379bbcSBoris Brezillon for (i = 0; i < sizeof(getpid->pid); i++) {
12043a379bbcSBoris Brezillon int sft = (sizeof(getpid->pid) - i - 1) * 8;
12053a379bbcSBoris Brezillon
12063a379bbcSBoris Brezillon info->pid |= (u64)getpid->pid[i] << sft;
12073a379bbcSBoris Brezillon }
12083a379bbcSBoris Brezillon
12093a379bbcSBoris Brezillon out:
12103a379bbcSBoris Brezillon i3c_ccc_cmd_dest_cleanup(&dest);
12113a379bbcSBoris Brezillon
12123a379bbcSBoris Brezillon return ret;
12133a379bbcSBoris Brezillon }
12143a379bbcSBoris Brezillon
i3c_master_getbcr_locked(struct i3c_master_controller * master,struct i3c_device_info * info)12153a379bbcSBoris Brezillon static int i3c_master_getbcr_locked(struct i3c_master_controller *master,
12163a379bbcSBoris Brezillon struct i3c_device_info *info)
12173a379bbcSBoris Brezillon {
12183a379bbcSBoris Brezillon struct i3c_ccc_getbcr *getbcr;
12193a379bbcSBoris Brezillon struct i3c_ccc_cmd_dest dest;
12203a379bbcSBoris Brezillon struct i3c_ccc_cmd cmd;
12213a379bbcSBoris Brezillon int ret;
12223a379bbcSBoris Brezillon
12233a379bbcSBoris Brezillon getbcr = i3c_ccc_cmd_dest_init(&dest, info->dyn_addr, sizeof(*getbcr));
12243a379bbcSBoris Brezillon if (!getbcr)
12253a379bbcSBoris Brezillon return -ENOMEM;
12263a379bbcSBoris Brezillon
12273a379bbcSBoris Brezillon i3c_ccc_cmd_init(&cmd, true, I3C_CCC_GETBCR, &dest, 1);
12283a379bbcSBoris Brezillon ret = i3c_master_send_ccc_cmd_locked(master, &cmd);
12293a379bbcSBoris Brezillon if (ret)
12303a379bbcSBoris Brezillon goto out;
12313a379bbcSBoris Brezillon
12323a379bbcSBoris Brezillon info->bcr = getbcr->bcr;
12333a379bbcSBoris Brezillon
12343a379bbcSBoris Brezillon out:
12353a379bbcSBoris Brezillon i3c_ccc_cmd_dest_cleanup(&dest);
12363a379bbcSBoris Brezillon
12373a379bbcSBoris Brezillon return ret;
12383a379bbcSBoris Brezillon }
12393a379bbcSBoris Brezillon
i3c_master_getdcr_locked(struct i3c_master_controller * master,struct i3c_device_info * info)12403a379bbcSBoris Brezillon static int i3c_master_getdcr_locked(struct i3c_master_controller *master,
12413a379bbcSBoris Brezillon struct i3c_device_info *info)
12423a379bbcSBoris Brezillon {
12433a379bbcSBoris Brezillon struct i3c_ccc_getdcr *getdcr;
12443a379bbcSBoris Brezillon struct i3c_ccc_cmd_dest dest;
12453a379bbcSBoris Brezillon struct i3c_ccc_cmd cmd;
12463a379bbcSBoris Brezillon int ret;
12473a379bbcSBoris Brezillon
12483a379bbcSBoris Brezillon getdcr = i3c_ccc_cmd_dest_init(&dest, info->dyn_addr, sizeof(*getdcr));
12493a379bbcSBoris Brezillon if (!getdcr)
12503a379bbcSBoris Brezillon return -ENOMEM;
12513a379bbcSBoris Brezillon
12523a379bbcSBoris Brezillon i3c_ccc_cmd_init(&cmd, true, I3C_CCC_GETDCR, &dest, 1);
12533a379bbcSBoris Brezillon ret = i3c_master_send_ccc_cmd_locked(master, &cmd);
12543a379bbcSBoris Brezillon if (ret)
12553a379bbcSBoris Brezillon goto out;
12563a379bbcSBoris Brezillon
12573a379bbcSBoris Brezillon info->dcr = getdcr->dcr;
12583a379bbcSBoris Brezillon
12593a379bbcSBoris Brezillon out:
12603a379bbcSBoris Brezillon i3c_ccc_cmd_dest_cleanup(&dest);
12613a379bbcSBoris Brezillon
12623a379bbcSBoris Brezillon return ret;
12633a379bbcSBoris Brezillon }
12643a379bbcSBoris Brezillon
i3c_master_retrieve_dev_info(struct i3c_dev_desc * dev)12653a379bbcSBoris Brezillon static int i3c_master_retrieve_dev_info(struct i3c_dev_desc *dev)
12663a379bbcSBoris Brezillon {
12673a379bbcSBoris Brezillon struct i3c_master_controller *master = i3c_dev_get_master(dev);
12683a379bbcSBoris Brezillon enum i3c_addr_slot_status slot_status;
12693a379bbcSBoris Brezillon int ret;
12703a379bbcSBoris Brezillon
12713a379bbcSBoris Brezillon if (!dev->info.dyn_addr)
12723a379bbcSBoris Brezillon return -EINVAL;
12733a379bbcSBoris Brezillon
12743a379bbcSBoris Brezillon slot_status = i3c_bus_get_addr_slot_status(&master->bus,
12753a379bbcSBoris Brezillon dev->info.dyn_addr);
12763a379bbcSBoris Brezillon if (slot_status == I3C_ADDR_SLOT_RSVD ||
12773a379bbcSBoris Brezillon slot_status == I3C_ADDR_SLOT_I2C_DEV)
12783a379bbcSBoris Brezillon return -EINVAL;
12793a379bbcSBoris Brezillon
12803a379bbcSBoris Brezillon ret = i3c_master_getpid_locked(master, &dev->info);
12813a379bbcSBoris Brezillon if (ret)
12823a379bbcSBoris Brezillon return ret;
12833a379bbcSBoris Brezillon
12843a379bbcSBoris Brezillon ret = i3c_master_getbcr_locked(master, &dev->info);
12853a379bbcSBoris Brezillon if (ret)
12863a379bbcSBoris Brezillon return ret;
12873a379bbcSBoris Brezillon
12883a379bbcSBoris Brezillon ret = i3c_master_getdcr_locked(master, &dev->info);
12893a379bbcSBoris Brezillon if (ret)
12903a379bbcSBoris Brezillon return ret;
12913a379bbcSBoris Brezillon
12923a379bbcSBoris Brezillon if (dev->info.bcr & I3C_BCR_MAX_DATA_SPEED_LIM) {
12933a379bbcSBoris Brezillon ret = i3c_master_getmxds_locked(master, &dev->info);
12943a379bbcSBoris Brezillon if (ret)
12953a379bbcSBoris Brezillon return ret;
12963a379bbcSBoris Brezillon }
12973a379bbcSBoris Brezillon
12983a379bbcSBoris Brezillon if (dev->info.bcr & I3C_BCR_IBI_PAYLOAD)
12993a379bbcSBoris Brezillon dev->info.max_ibi_len = 1;
13003a379bbcSBoris Brezillon
13013a379bbcSBoris Brezillon i3c_master_getmrl_locked(master, &dev->info);
13023a379bbcSBoris Brezillon i3c_master_getmwl_locked(master, &dev->info);
13033a379bbcSBoris Brezillon
13043a379bbcSBoris Brezillon if (dev->info.bcr & I3C_BCR_HDR_CAP) {
13053a379bbcSBoris Brezillon ret = i3c_master_gethdrcap_locked(master, &dev->info);
13063a379bbcSBoris Brezillon if (ret)
13073a379bbcSBoris Brezillon return ret;
13083a379bbcSBoris Brezillon }
13093a379bbcSBoris Brezillon
13103a379bbcSBoris Brezillon return 0;
13113a379bbcSBoris Brezillon }
13123a379bbcSBoris Brezillon
i3c_master_put_i3c_addrs(struct i3c_dev_desc * dev)13133a379bbcSBoris Brezillon static void i3c_master_put_i3c_addrs(struct i3c_dev_desc *dev)
13143a379bbcSBoris Brezillon {
13153a379bbcSBoris Brezillon struct i3c_master_controller *master = i3c_dev_get_master(dev);
13163a379bbcSBoris Brezillon
13173a379bbcSBoris Brezillon if (dev->info.static_addr)
13183a379bbcSBoris Brezillon i3c_bus_set_addr_slot_status(&master->bus,
13193a379bbcSBoris Brezillon dev->info.static_addr,
13203a379bbcSBoris Brezillon I3C_ADDR_SLOT_FREE);
13213a379bbcSBoris Brezillon
13223a379bbcSBoris Brezillon if (dev->info.dyn_addr)
13233a379bbcSBoris Brezillon i3c_bus_set_addr_slot_status(&master->bus, dev->info.dyn_addr,
13243a379bbcSBoris Brezillon I3C_ADDR_SLOT_FREE);
13253a379bbcSBoris Brezillon
13263a379bbcSBoris Brezillon if (dev->boardinfo && dev->boardinfo->init_dyn_addr)
13273a379bbcSBoris Brezillon i3c_bus_set_addr_slot_status(&master->bus, dev->info.dyn_addr,
13283a379bbcSBoris Brezillon I3C_ADDR_SLOT_FREE);
13293a379bbcSBoris Brezillon }
13303a379bbcSBoris Brezillon
i3c_master_get_i3c_addrs(struct i3c_dev_desc * dev)13313a379bbcSBoris Brezillon static int i3c_master_get_i3c_addrs(struct i3c_dev_desc *dev)
13323a379bbcSBoris Brezillon {
13333a379bbcSBoris Brezillon struct i3c_master_controller *master = i3c_dev_get_master(dev);
13343a379bbcSBoris Brezillon enum i3c_addr_slot_status status;
13353a379bbcSBoris Brezillon
13363a379bbcSBoris Brezillon if (!dev->info.static_addr && !dev->info.dyn_addr)
13373a379bbcSBoris Brezillon return 0;
13383a379bbcSBoris Brezillon
13393a379bbcSBoris Brezillon if (dev->info.static_addr) {
13403a379bbcSBoris Brezillon status = i3c_bus_get_addr_slot_status(&master->bus,
13413a379bbcSBoris Brezillon dev->info.static_addr);
1342c6a75504SAniket /* Since static address and assigned dynamic address can be
1343c6a75504SAniket * equal, allow this case to pass.
1344c6a75504SAniket */
1345c6a75504SAniket if (status != I3C_ADDR_SLOT_FREE &&
1346c6a75504SAniket dev->info.static_addr != dev->boardinfo->init_dyn_addr)
13473a379bbcSBoris Brezillon return -EBUSY;
13483a379bbcSBoris Brezillon
13493a379bbcSBoris Brezillon i3c_bus_set_addr_slot_status(&master->bus,
13503a379bbcSBoris Brezillon dev->info.static_addr,
13513a379bbcSBoris Brezillon I3C_ADDR_SLOT_I3C_DEV);
13523a379bbcSBoris Brezillon }
13533a379bbcSBoris Brezillon
13543a379bbcSBoris Brezillon /*
13553a379bbcSBoris Brezillon * ->init_dyn_addr should have been reserved before that, so, if we're
13563a379bbcSBoris Brezillon * trying to apply a pre-reserved dynamic address, we should not try
13573a379bbcSBoris Brezillon * to reserve the address slot a second time.
13583a379bbcSBoris Brezillon */
13593a379bbcSBoris Brezillon if (dev->info.dyn_addr &&
13603a379bbcSBoris Brezillon (!dev->boardinfo ||
13613a379bbcSBoris Brezillon dev->boardinfo->init_dyn_addr != dev->info.dyn_addr)) {
13623a379bbcSBoris Brezillon status = i3c_bus_get_addr_slot_status(&master->bus,
13633a379bbcSBoris Brezillon dev->info.dyn_addr);
13643a379bbcSBoris Brezillon if (status != I3C_ADDR_SLOT_FREE)
13653a379bbcSBoris Brezillon goto err_release_static_addr;
13663a379bbcSBoris Brezillon
13673a379bbcSBoris Brezillon i3c_bus_set_addr_slot_status(&master->bus, dev->info.dyn_addr,
13683a379bbcSBoris Brezillon I3C_ADDR_SLOT_I3C_DEV);
13693a379bbcSBoris Brezillon }
13703a379bbcSBoris Brezillon
13713a379bbcSBoris Brezillon return 0;
13723a379bbcSBoris Brezillon
13733a379bbcSBoris Brezillon err_release_static_addr:
13743a379bbcSBoris Brezillon if (dev->info.static_addr)
13753a379bbcSBoris Brezillon i3c_bus_set_addr_slot_status(&master->bus,
13763a379bbcSBoris Brezillon dev->info.static_addr,
13773a379bbcSBoris Brezillon I3C_ADDR_SLOT_FREE);
13783a379bbcSBoris Brezillon
13793a379bbcSBoris Brezillon return -EBUSY;
13803a379bbcSBoris Brezillon }
13813a379bbcSBoris Brezillon
i3c_master_attach_i3c_dev(struct i3c_master_controller * master,struct i3c_dev_desc * dev)13823a379bbcSBoris Brezillon static int i3c_master_attach_i3c_dev(struct i3c_master_controller *master,
13833a379bbcSBoris Brezillon struct i3c_dev_desc *dev)
13843a379bbcSBoris Brezillon {
13853a379bbcSBoris Brezillon int ret;
13863a379bbcSBoris Brezillon
13873a379bbcSBoris Brezillon /*
13883a379bbcSBoris Brezillon * We don't attach devices to the controller until they are
13893a379bbcSBoris Brezillon * addressable on the bus.
13903a379bbcSBoris Brezillon */
13913a379bbcSBoris Brezillon if (!dev->info.static_addr && !dev->info.dyn_addr)
13923a379bbcSBoris Brezillon return 0;
13933a379bbcSBoris Brezillon
13943a379bbcSBoris Brezillon ret = i3c_master_get_i3c_addrs(dev);
13953a379bbcSBoris Brezillon if (ret)
13963a379bbcSBoris Brezillon return ret;
13973a379bbcSBoris Brezillon
13983a379bbcSBoris Brezillon /* Do not attach the master device itself. */
13993a379bbcSBoris Brezillon if (master->this != dev && master->ops->attach_i3c_dev) {
14003a379bbcSBoris Brezillon ret = master->ops->attach_i3c_dev(dev);
14013a379bbcSBoris Brezillon if (ret) {
14023a379bbcSBoris Brezillon i3c_master_put_i3c_addrs(dev);
14033a379bbcSBoris Brezillon return ret;
14043a379bbcSBoris Brezillon }
14053a379bbcSBoris Brezillon }
14063a379bbcSBoris Brezillon
14073a379bbcSBoris Brezillon list_add_tail(&dev->common.node, &master->bus.devs.i3c);
14083a379bbcSBoris Brezillon
14093a379bbcSBoris Brezillon return 0;
14103a379bbcSBoris Brezillon }
14113a379bbcSBoris Brezillon
i3c_master_reattach_i3c_dev(struct i3c_dev_desc * dev,u8 old_dyn_addr)14123a379bbcSBoris Brezillon static int i3c_master_reattach_i3c_dev(struct i3c_dev_desc *dev,
14133a379bbcSBoris Brezillon u8 old_dyn_addr)
14143a379bbcSBoris Brezillon {
14153a379bbcSBoris Brezillon struct i3c_master_controller *master = i3c_dev_get_master(dev);
14163a379bbcSBoris Brezillon enum i3c_addr_slot_status status;
14173a379bbcSBoris Brezillon int ret;
14183a379bbcSBoris Brezillon
1419cc3a392dSParshuram Thombare if (dev->info.dyn_addr != old_dyn_addr &&
1420cc3a392dSParshuram Thombare (!dev->boardinfo ||
1421cc3a392dSParshuram Thombare dev->info.dyn_addr != dev->boardinfo->init_dyn_addr)) {
14223a379bbcSBoris Brezillon status = i3c_bus_get_addr_slot_status(&master->bus,
14233a379bbcSBoris Brezillon dev->info.dyn_addr);
14243a379bbcSBoris Brezillon if (status != I3C_ADDR_SLOT_FREE)
14253a379bbcSBoris Brezillon return -EBUSY;
14263a379bbcSBoris Brezillon i3c_bus_set_addr_slot_status(&master->bus,
14273a379bbcSBoris Brezillon dev->info.dyn_addr,
14283a379bbcSBoris Brezillon I3C_ADDR_SLOT_I3C_DEV);
1429d4fa7d77SBilly Tsai if (old_dyn_addr)
1430d4fa7d77SBilly Tsai i3c_bus_set_addr_slot_status(&master->bus, old_dyn_addr,
1431d4fa7d77SBilly Tsai I3C_ADDR_SLOT_FREE);
14323a379bbcSBoris Brezillon }
14333a379bbcSBoris Brezillon
14343a379bbcSBoris Brezillon if (master->ops->reattach_i3c_dev) {
14353a379bbcSBoris Brezillon ret = master->ops->reattach_i3c_dev(dev, old_dyn_addr);
14363a379bbcSBoris Brezillon if (ret) {
14373a379bbcSBoris Brezillon i3c_master_put_i3c_addrs(dev);
14383a379bbcSBoris Brezillon return ret;
14393a379bbcSBoris Brezillon }
14403a379bbcSBoris Brezillon }
14413a379bbcSBoris Brezillon
14423a379bbcSBoris Brezillon return 0;
14433a379bbcSBoris Brezillon }
14443a379bbcSBoris Brezillon
i3c_master_detach_i3c_dev(struct i3c_dev_desc * dev)14453a379bbcSBoris Brezillon static void i3c_master_detach_i3c_dev(struct i3c_dev_desc *dev)
14463a379bbcSBoris Brezillon {
14473a379bbcSBoris Brezillon struct i3c_master_controller *master = i3c_dev_get_master(dev);
14483a379bbcSBoris Brezillon
14493a379bbcSBoris Brezillon /* Do not detach the master device itself. */
14503a379bbcSBoris Brezillon if (master->this != dev && master->ops->detach_i3c_dev)
14513a379bbcSBoris Brezillon master->ops->detach_i3c_dev(dev);
14523a379bbcSBoris Brezillon
14533a379bbcSBoris Brezillon i3c_master_put_i3c_addrs(dev);
14543a379bbcSBoris Brezillon list_del(&dev->common.node);
14553a379bbcSBoris Brezillon }
14563a379bbcSBoris Brezillon
i3c_master_attach_i2c_dev(struct i3c_master_controller * master,struct i2c_dev_desc * dev)14573a379bbcSBoris Brezillon static int i3c_master_attach_i2c_dev(struct i3c_master_controller *master,
14583a379bbcSBoris Brezillon struct i2c_dev_desc *dev)
14593a379bbcSBoris Brezillon {
14603a379bbcSBoris Brezillon int ret;
14613a379bbcSBoris Brezillon
14623a379bbcSBoris Brezillon if (master->ops->attach_i2c_dev) {
14633a379bbcSBoris Brezillon ret = master->ops->attach_i2c_dev(dev);
14643a379bbcSBoris Brezillon if (ret)
14653a379bbcSBoris Brezillon return ret;
14663a379bbcSBoris Brezillon }
14673a379bbcSBoris Brezillon
14683a379bbcSBoris Brezillon list_add_tail(&dev->common.node, &master->bus.devs.i2c);
14693a379bbcSBoris Brezillon
14703a379bbcSBoris Brezillon return 0;
14713a379bbcSBoris Brezillon }
14723a379bbcSBoris Brezillon
i3c_master_detach_i2c_dev(struct i2c_dev_desc * dev)14733a379bbcSBoris Brezillon static void i3c_master_detach_i2c_dev(struct i2c_dev_desc *dev)
14743a379bbcSBoris Brezillon {
14753a379bbcSBoris Brezillon struct i3c_master_controller *master = i2c_dev_get_master(dev);
14763a379bbcSBoris Brezillon
14773a379bbcSBoris Brezillon list_del(&dev->common.node);
14783a379bbcSBoris Brezillon
14793a379bbcSBoris Brezillon if (master->ops->detach_i2c_dev)
14803a379bbcSBoris Brezillon master->ops->detach_i2c_dev(dev);
14813a379bbcSBoris Brezillon }
14823a379bbcSBoris Brezillon
i3c_master_early_i3c_dev_add(struct i3c_master_controller * master,struct i3c_dev_boardinfo * boardinfo)1483cc3a392dSParshuram Thombare static int i3c_master_early_i3c_dev_add(struct i3c_master_controller *master,
1484cc3a392dSParshuram Thombare struct i3c_dev_boardinfo *boardinfo)
14853a379bbcSBoris Brezillon {
1486cc3a392dSParshuram Thombare struct i3c_device_info info = {
1487cc3a392dSParshuram Thombare .static_addr = boardinfo->static_addr,
1488f195c470SJack Chen .pid = boardinfo->pid,
1489cc3a392dSParshuram Thombare };
1490cc3a392dSParshuram Thombare struct i3c_dev_desc *i3cdev;
14913a379bbcSBoris Brezillon int ret;
14923a379bbcSBoris Brezillon
1493cc3a392dSParshuram Thombare i3cdev = i3c_master_alloc_i3c_dev(master, &info);
1494cc3a392dSParshuram Thombare if (IS_ERR(i3cdev))
1495cc3a392dSParshuram Thombare return -ENOMEM;
14963a379bbcSBoris Brezillon
1497cc3a392dSParshuram Thombare i3cdev->boardinfo = boardinfo;
1498cc3a392dSParshuram Thombare
1499cc3a392dSParshuram Thombare ret = i3c_master_attach_i3c_dev(master, i3cdev);
15003a379bbcSBoris Brezillon if (ret)
1501cc3a392dSParshuram Thombare goto err_free_dev;
15023a379bbcSBoris Brezillon
1503cc3a392dSParshuram Thombare ret = i3c_master_setdasa_locked(master, i3cdev->info.static_addr,
1504cc3a392dSParshuram Thombare i3cdev->boardinfo->init_dyn_addr);
1505cc3a392dSParshuram Thombare if (ret)
1506cc3a392dSParshuram Thombare goto err_detach_dev;
1507cc3a392dSParshuram Thombare
1508cc3a392dSParshuram Thombare i3cdev->info.dyn_addr = i3cdev->boardinfo->init_dyn_addr;
1509cc3a392dSParshuram Thombare ret = i3c_master_reattach_i3c_dev(i3cdev, 0);
15103a379bbcSBoris Brezillon if (ret)
15113a379bbcSBoris Brezillon goto err_rstdaa;
15123a379bbcSBoris Brezillon
1513cc3a392dSParshuram Thombare ret = i3c_master_retrieve_dev_info(i3cdev);
15143a379bbcSBoris Brezillon if (ret)
15153a379bbcSBoris Brezillon goto err_rstdaa;
15163a379bbcSBoris Brezillon
1517cc3a392dSParshuram Thombare return 0;
15183a379bbcSBoris Brezillon
15193a379bbcSBoris Brezillon err_rstdaa:
1520cc3a392dSParshuram Thombare i3c_master_rstdaa_locked(master, i3cdev->boardinfo->init_dyn_addr);
1521cc3a392dSParshuram Thombare err_detach_dev:
1522cc3a392dSParshuram Thombare i3c_master_detach_i3c_dev(i3cdev);
1523cc3a392dSParshuram Thombare err_free_dev:
1524cc3a392dSParshuram Thombare i3c_master_free_i3c_dev(i3cdev);
1525cc3a392dSParshuram Thombare
1526cc3a392dSParshuram Thombare return ret;
15273a379bbcSBoris Brezillon }
15283a379bbcSBoris Brezillon
15293a379bbcSBoris Brezillon static void
i3c_master_register_new_i3c_devs(struct i3c_master_controller * master)15303a379bbcSBoris Brezillon i3c_master_register_new_i3c_devs(struct i3c_master_controller *master)
15313a379bbcSBoris Brezillon {
15323a379bbcSBoris Brezillon struct i3c_dev_desc *desc;
15333a379bbcSBoris Brezillon int ret;
15343a379bbcSBoris Brezillon
15353a379bbcSBoris Brezillon if (!master->init_done)
15363a379bbcSBoris Brezillon return;
15373a379bbcSBoris Brezillon
15383a379bbcSBoris Brezillon i3c_bus_for_each_i3cdev(&master->bus, desc) {
15393a379bbcSBoris Brezillon if (desc->dev || !desc->info.dyn_addr || desc == master->this)
15403a379bbcSBoris Brezillon continue;
15413a379bbcSBoris Brezillon
15423a379bbcSBoris Brezillon desc->dev = kzalloc(sizeof(*desc->dev), GFP_KERNEL);
15433a379bbcSBoris Brezillon if (!desc->dev)
15443a379bbcSBoris Brezillon continue;
15453a379bbcSBoris Brezillon
15463a379bbcSBoris Brezillon desc->dev->bus = &master->bus;
15473a379bbcSBoris Brezillon desc->dev->desc = desc;
15483a379bbcSBoris Brezillon desc->dev->dev.parent = &master->dev;
15493a379bbcSBoris Brezillon desc->dev->dev.type = &i3c_device_type;
15503a379bbcSBoris Brezillon desc->dev->dev.bus = &i3c_bus_type;
15513a379bbcSBoris Brezillon desc->dev->dev.release = i3c_device_release;
15523a379bbcSBoris Brezillon dev_set_name(&desc->dev->dev, "%d-%llx", master->bus.id,
15533a379bbcSBoris Brezillon desc->info.pid);
15543a379bbcSBoris Brezillon
15553a379bbcSBoris Brezillon if (desc->boardinfo)
15563a379bbcSBoris Brezillon desc->dev->dev.of_node = desc->boardinfo->of_node;
15573a379bbcSBoris Brezillon
15583a379bbcSBoris Brezillon ret = device_register(&desc->dev->dev);
1559e49a51a9SDinghao Liu if (ret) {
15603a379bbcSBoris Brezillon dev_err(&master->dev,
15613a379bbcSBoris Brezillon "Failed to add I3C device (err = %d)\n", ret);
1562e49a51a9SDinghao Liu put_device(&desc->dev->dev);
1563e49a51a9SDinghao Liu }
15643a379bbcSBoris Brezillon }
15653a379bbcSBoris Brezillon }
15663a379bbcSBoris Brezillon
15673a379bbcSBoris Brezillon /**
15683a379bbcSBoris Brezillon * i3c_master_do_daa() - do a DAA (Dynamic Address Assignment)
15693a379bbcSBoris Brezillon * @master: master doing the DAA
15703a379bbcSBoris Brezillon *
15713a379bbcSBoris Brezillon * This function is instantiating an I3C device object and adding it to the
15723a379bbcSBoris Brezillon * I3C device list. All device information are automatically retrieved using
15733a379bbcSBoris Brezillon * standard CCC commands.
15743a379bbcSBoris Brezillon *
15753a379bbcSBoris Brezillon * The I3C device object is returned in case the master wants to attach
15763a379bbcSBoris Brezillon * private data to it using i3c_dev_set_master_data().
15773a379bbcSBoris Brezillon *
15783a379bbcSBoris Brezillon * This function must be called with the bus lock held in write mode.
15793a379bbcSBoris Brezillon *
15803a379bbcSBoris Brezillon * Return: a 0 in case of success, an negative error code otherwise.
15813a379bbcSBoris Brezillon */
i3c_master_do_daa(struct i3c_master_controller * master)15823a379bbcSBoris Brezillon int i3c_master_do_daa(struct i3c_master_controller *master)
15833a379bbcSBoris Brezillon {
15843a379bbcSBoris Brezillon int ret;
15853a379bbcSBoris Brezillon
15863a379bbcSBoris Brezillon i3c_bus_maintenance_lock(&master->bus);
15873a379bbcSBoris Brezillon ret = master->ops->do_daa(master);
15883a379bbcSBoris Brezillon i3c_bus_maintenance_unlock(&master->bus);
15893a379bbcSBoris Brezillon
15903a379bbcSBoris Brezillon if (ret)
15913a379bbcSBoris Brezillon return ret;
15923a379bbcSBoris Brezillon
15933a379bbcSBoris Brezillon i3c_bus_normaluse_lock(&master->bus);
15943a379bbcSBoris Brezillon i3c_master_register_new_i3c_devs(master);
15953a379bbcSBoris Brezillon i3c_bus_normaluse_unlock(&master->bus);
15963a379bbcSBoris Brezillon
15973a379bbcSBoris Brezillon return 0;
15983a379bbcSBoris Brezillon }
15993a379bbcSBoris Brezillon EXPORT_SYMBOL_GPL(i3c_master_do_daa);
16003a379bbcSBoris Brezillon
16013a379bbcSBoris Brezillon /**
16023a379bbcSBoris Brezillon * i3c_master_set_info() - set master device information
16033a379bbcSBoris Brezillon * @master: master used to send frames on the bus
16043a379bbcSBoris Brezillon * @info: I3C device information
16053a379bbcSBoris Brezillon *
16063a379bbcSBoris Brezillon * Set master device info. This should be called from
16073a379bbcSBoris Brezillon * &i3c_master_controller_ops->bus_init().
16083a379bbcSBoris Brezillon *
16093a379bbcSBoris Brezillon * Not all &i3c_device_info fields are meaningful for a master device.
16103a379bbcSBoris Brezillon * Here is a list of fields that should be properly filled:
16113a379bbcSBoris Brezillon *
16123a379bbcSBoris Brezillon * - &i3c_device_info->dyn_addr
16133a379bbcSBoris Brezillon * - &i3c_device_info->bcr
16143a379bbcSBoris Brezillon * - &i3c_device_info->dcr
16153a379bbcSBoris Brezillon * - &i3c_device_info->pid
16163a379bbcSBoris Brezillon * - &i3c_device_info->hdr_cap if %I3C_BCR_HDR_CAP bit is set in
16173a379bbcSBoris Brezillon * &i3c_device_info->bcr
16183a379bbcSBoris Brezillon *
16193a379bbcSBoris Brezillon * This function must be called with the bus lock held in maintenance mode.
16203a379bbcSBoris Brezillon *
16213a379bbcSBoris Brezillon * Return: 0 if @info contains valid information (not every piece of
16223a379bbcSBoris Brezillon * information can be checked, but we can at least make sure @info->dyn_addr
16233a379bbcSBoris Brezillon * and @info->bcr are correct), -EINVAL otherwise.
16243a379bbcSBoris Brezillon */
i3c_master_set_info(struct i3c_master_controller * master,const struct i3c_device_info * info)16253a379bbcSBoris Brezillon int i3c_master_set_info(struct i3c_master_controller *master,
16263a379bbcSBoris Brezillon const struct i3c_device_info *info)
16273a379bbcSBoris Brezillon {
16283a379bbcSBoris Brezillon struct i3c_dev_desc *i3cdev;
16293a379bbcSBoris Brezillon int ret;
16303a379bbcSBoris Brezillon
16313a379bbcSBoris Brezillon if (!i3c_bus_dev_addr_is_avail(&master->bus, info->dyn_addr))
16323a379bbcSBoris Brezillon return -EINVAL;
16333a379bbcSBoris Brezillon
16343a379bbcSBoris Brezillon if (I3C_BCR_DEVICE_ROLE(info->bcr) == I3C_BCR_I3C_MASTER &&
16353a379bbcSBoris Brezillon master->secondary)
16363a379bbcSBoris Brezillon return -EINVAL;
16373a379bbcSBoris Brezillon
16383a379bbcSBoris Brezillon if (master->this)
16393a379bbcSBoris Brezillon return -EINVAL;
16403a379bbcSBoris Brezillon
16413a379bbcSBoris Brezillon i3cdev = i3c_master_alloc_i3c_dev(master, info);
16423a379bbcSBoris Brezillon if (IS_ERR(i3cdev))
16433a379bbcSBoris Brezillon return PTR_ERR(i3cdev);
16443a379bbcSBoris Brezillon
16453a379bbcSBoris Brezillon master->this = i3cdev;
16463a379bbcSBoris Brezillon master->bus.cur_master = master->this;
16473a379bbcSBoris Brezillon
16483a379bbcSBoris Brezillon ret = i3c_master_attach_i3c_dev(master, i3cdev);
16493a379bbcSBoris Brezillon if (ret)
16503a379bbcSBoris Brezillon goto err_free_dev;
16513a379bbcSBoris Brezillon
16523a379bbcSBoris Brezillon return 0;
16533a379bbcSBoris Brezillon
16543a379bbcSBoris Brezillon err_free_dev:
16553a379bbcSBoris Brezillon i3c_master_free_i3c_dev(i3cdev);
16563a379bbcSBoris Brezillon
16573a379bbcSBoris Brezillon return ret;
16583a379bbcSBoris Brezillon }
16593a379bbcSBoris Brezillon EXPORT_SYMBOL_GPL(i3c_master_set_info);
16603a379bbcSBoris Brezillon
i3c_master_detach_free_devs(struct i3c_master_controller * master)16613a379bbcSBoris Brezillon static void i3c_master_detach_free_devs(struct i3c_master_controller *master)
16623a379bbcSBoris Brezillon {
16633a379bbcSBoris Brezillon struct i3c_dev_desc *i3cdev, *i3ctmp;
16643a379bbcSBoris Brezillon struct i2c_dev_desc *i2cdev, *i2ctmp;
16653a379bbcSBoris Brezillon
16663a379bbcSBoris Brezillon list_for_each_entry_safe(i3cdev, i3ctmp, &master->bus.devs.i3c,
16673a379bbcSBoris Brezillon common.node) {
16683a379bbcSBoris Brezillon i3c_master_detach_i3c_dev(i3cdev);
16693a379bbcSBoris Brezillon
16703a379bbcSBoris Brezillon if (i3cdev->boardinfo && i3cdev->boardinfo->init_dyn_addr)
16713a379bbcSBoris Brezillon i3c_bus_set_addr_slot_status(&master->bus,
16723a379bbcSBoris Brezillon i3cdev->boardinfo->init_dyn_addr,
16733a379bbcSBoris Brezillon I3C_ADDR_SLOT_FREE);
16743a379bbcSBoris Brezillon
16753a379bbcSBoris Brezillon i3c_master_free_i3c_dev(i3cdev);
16763a379bbcSBoris Brezillon }
16773a379bbcSBoris Brezillon
16783a379bbcSBoris Brezillon list_for_each_entry_safe(i2cdev, i2ctmp, &master->bus.devs.i2c,
16793a379bbcSBoris Brezillon common.node) {
16803a379bbcSBoris Brezillon i3c_master_detach_i2c_dev(i2cdev);
16813a379bbcSBoris Brezillon i3c_bus_set_addr_slot_status(&master->bus,
1682b1ac3a4bSPrzemyslaw Gaj i2cdev->addr,
16833a379bbcSBoris Brezillon I3C_ADDR_SLOT_FREE);
16843a379bbcSBoris Brezillon i3c_master_free_i2c_dev(i2cdev);
16853a379bbcSBoris Brezillon }
16863a379bbcSBoris Brezillon }
16873a379bbcSBoris Brezillon
16883a379bbcSBoris Brezillon /**
16893a379bbcSBoris Brezillon * i3c_master_bus_init() - initialize an I3C bus
16903a379bbcSBoris Brezillon * @master: main master initializing the bus
16913a379bbcSBoris Brezillon *
16923a379bbcSBoris Brezillon * This function is following all initialisation steps described in the I3C
16933a379bbcSBoris Brezillon * specification:
16943a379bbcSBoris Brezillon *
1695cc3a392dSParshuram Thombare * 1. Attach I2C devs to the master so that the master can fill its internal
1696cc3a392dSParshuram Thombare * device table appropriately
16973a379bbcSBoris Brezillon *
16983a379bbcSBoris Brezillon * 2. Call &i3c_master_controller_ops->bus_init() method to initialize
16993a379bbcSBoris Brezillon * the master controller. That's usually where the bus mode is selected
17003a379bbcSBoris Brezillon * (pure bus or mixed fast/slow bus)
17013a379bbcSBoris Brezillon *
17023a379bbcSBoris Brezillon * 3. Instruct all devices on the bus to drop their dynamic address. This is
17033a379bbcSBoris Brezillon * particularly important when the bus was previously configured by someone
17043a379bbcSBoris Brezillon * else (for example the bootloader)
17053a379bbcSBoris Brezillon *
17063a379bbcSBoris Brezillon * 4. Disable all slave events.
17073a379bbcSBoris Brezillon *
1708cc3a392dSParshuram Thombare * 5. Reserve address slots for I3C devices with init_dyn_addr. And if devices
1709cc3a392dSParshuram Thombare * also have static_addr, try to pre-assign dynamic addresses requested by
1710cc3a392dSParshuram Thombare * the FW with SETDASA and attach corresponding statically defined I3C
1711cc3a392dSParshuram Thombare * devices to the master.
17123a379bbcSBoris Brezillon *
17133a379bbcSBoris Brezillon * 6. Do a DAA (Dynamic Address Assignment) to assign dynamic addresses to all
17143a379bbcSBoris Brezillon * remaining I3C devices
17153a379bbcSBoris Brezillon *
17163a379bbcSBoris Brezillon * Once this is done, all I3C and I2C devices should be usable.
17173a379bbcSBoris Brezillon *
17183a379bbcSBoris Brezillon * Return: a 0 in case of success, an negative error code otherwise.
17193a379bbcSBoris Brezillon */
i3c_master_bus_init(struct i3c_master_controller * master)17203a379bbcSBoris Brezillon static int i3c_master_bus_init(struct i3c_master_controller *master)
17213a379bbcSBoris Brezillon {
17223a379bbcSBoris Brezillon enum i3c_addr_slot_status status;
17233a379bbcSBoris Brezillon struct i2c_dev_boardinfo *i2cboardinfo;
17243a379bbcSBoris Brezillon struct i3c_dev_boardinfo *i3cboardinfo;
17253a379bbcSBoris Brezillon struct i2c_dev_desc *i2cdev;
17263a379bbcSBoris Brezillon int ret;
17273a379bbcSBoris Brezillon
17283a379bbcSBoris Brezillon /*
17293a379bbcSBoris Brezillon * First attach all devices with static definitions provided by the
17303a379bbcSBoris Brezillon * FW.
17313a379bbcSBoris Brezillon */
17323a379bbcSBoris Brezillon list_for_each_entry(i2cboardinfo, &master->boardinfo.i2c, node) {
17333a379bbcSBoris Brezillon status = i3c_bus_get_addr_slot_status(&master->bus,
17343a379bbcSBoris Brezillon i2cboardinfo->base.addr);
17353a379bbcSBoris Brezillon if (status != I3C_ADDR_SLOT_FREE) {
17363a379bbcSBoris Brezillon ret = -EBUSY;
17373a379bbcSBoris Brezillon goto err_detach_devs;
17383a379bbcSBoris Brezillon }
17393a379bbcSBoris Brezillon
17403a379bbcSBoris Brezillon i3c_bus_set_addr_slot_status(&master->bus,
17413a379bbcSBoris Brezillon i2cboardinfo->base.addr,
17423a379bbcSBoris Brezillon I3C_ADDR_SLOT_I2C_DEV);
17433a379bbcSBoris Brezillon
174431b9887cSJamie Iles i2cdev = i3c_master_alloc_i2c_dev(master,
174531b9887cSJamie Iles i2cboardinfo->base.addr,
174631b9887cSJamie Iles i2cboardinfo->lvr);
17473a379bbcSBoris Brezillon if (IS_ERR(i2cdev)) {
17483a379bbcSBoris Brezillon ret = PTR_ERR(i2cdev);
17493a379bbcSBoris Brezillon goto err_detach_devs;
17503a379bbcSBoris Brezillon }
17513a379bbcSBoris Brezillon
17523a379bbcSBoris Brezillon ret = i3c_master_attach_i2c_dev(master, i2cdev);
17533a379bbcSBoris Brezillon if (ret) {
17543a379bbcSBoris Brezillon i3c_master_free_i2c_dev(i2cdev);
17553a379bbcSBoris Brezillon goto err_detach_devs;
17563a379bbcSBoris Brezillon }
17573a379bbcSBoris Brezillon }
17583a379bbcSBoris Brezillon
17593a379bbcSBoris Brezillon /*
17603a379bbcSBoris Brezillon * Now execute the controller specific ->bus_init() routine, which
17613a379bbcSBoris Brezillon * might configure its internal logic to match the bus limitations.
17623a379bbcSBoris Brezillon */
17633a379bbcSBoris Brezillon ret = master->ops->bus_init(master);
17643a379bbcSBoris Brezillon if (ret)
17653a379bbcSBoris Brezillon goto err_detach_devs;
17663a379bbcSBoris Brezillon
17673a379bbcSBoris Brezillon /*
17683a379bbcSBoris Brezillon * The master device should have been instantiated in ->bus_init(),
17693a379bbcSBoris Brezillon * complain if this was not the case.
17703a379bbcSBoris Brezillon */
17713a379bbcSBoris Brezillon if (!master->this) {
17723a379bbcSBoris Brezillon dev_err(&master->dev,
17733a379bbcSBoris Brezillon "master_set_info() was not called in ->bus_init()\n");
17743a379bbcSBoris Brezillon ret = -EINVAL;
17753a379bbcSBoris Brezillon goto err_bus_cleanup;
17763a379bbcSBoris Brezillon }
17773a379bbcSBoris Brezillon
17783a379bbcSBoris Brezillon /*
17793a379bbcSBoris Brezillon * Reset all dynamic address that may have been assigned before
17803a379bbcSBoris Brezillon * (assigned by the bootloader for example).
17813a379bbcSBoris Brezillon */
17823a379bbcSBoris Brezillon ret = i3c_master_rstdaa_locked(master, I3C_BROADCAST_ADDR);
17833a379bbcSBoris Brezillon if (ret && ret != I3C_ERROR_M2)
17843a379bbcSBoris Brezillon goto err_bus_cleanup;
17853a379bbcSBoris Brezillon
17863a379bbcSBoris Brezillon /* Disable all slave events before starting DAA. */
17873a379bbcSBoris Brezillon ret = i3c_master_disec_locked(master, I3C_BROADCAST_ADDR,
17883a379bbcSBoris Brezillon I3C_CCC_EVENT_SIR | I3C_CCC_EVENT_MR |
17893a379bbcSBoris Brezillon I3C_CCC_EVENT_HJ);
17903a379bbcSBoris Brezillon if (ret && ret != I3C_ERROR_M2)
17913a379bbcSBoris Brezillon goto err_bus_cleanup;
17923a379bbcSBoris Brezillon
17933a379bbcSBoris Brezillon /*
1794cc3a392dSParshuram Thombare * Reserve init_dyn_addr first, and then try to pre-assign dynamic
1795cc3a392dSParshuram Thombare * address and retrieve device information if needed.
1796cc3a392dSParshuram Thombare * In case pre-assign dynamic address fails, setting dynamic address to
1797cc3a392dSParshuram Thombare * the requested init_dyn_addr is retried after DAA is done in
1798cc3a392dSParshuram Thombare * i3c_master_add_i3c_dev_locked().
17993a379bbcSBoris Brezillon */
1800cc3a392dSParshuram Thombare list_for_each_entry(i3cboardinfo, &master->boardinfo.i3c, node) {
1801cc3a392dSParshuram Thombare
1802cc3a392dSParshuram Thombare /*
1803cc3a392dSParshuram Thombare * We don't reserve a dynamic address for devices that
1804cc3a392dSParshuram Thombare * don't explicitly request one.
1805cc3a392dSParshuram Thombare */
1806cc3a392dSParshuram Thombare if (!i3cboardinfo->init_dyn_addr)
1807cc3a392dSParshuram Thombare continue;
1808cc3a392dSParshuram Thombare
1809cc3a392dSParshuram Thombare ret = i3c_bus_get_addr_slot_status(&master->bus,
1810cc3a392dSParshuram Thombare i3cboardinfo->init_dyn_addr);
1811cc3a392dSParshuram Thombare if (ret != I3C_ADDR_SLOT_FREE) {
1812cc3a392dSParshuram Thombare ret = -EBUSY;
1813cc3a392dSParshuram Thombare goto err_rstdaa;
1814cc3a392dSParshuram Thombare }
1815cc3a392dSParshuram Thombare
1816cc3a392dSParshuram Thombare i3c_bus_set_addr_slot_status(&master->bus,
1817cc3a392dSParshuram Thombare i3cboardinfo->init_dyn_addr,
1818cc3a392dSParshuram Thombare I3C_ADDR_SLOT_I3C_DEV);
1819cc3a392dSParshuram Thombare
1820cc3a392dSParshuram Thombare /*
1821cc3a392dSParshuram Thombare * Only try to create/attach devices that have a static
1822cc3a392dSParshuram Thombare * address. Other devices will be created/attached when
1823cc3a392dSParshuram Thombare * DAA happens, and the requested dynamic address will
1824cc3a392dSParshuram Thombare * be set using SETNEWDA once those devices become
1825cc3a392dSParshuram Thombare * addressable.
1826cc3a392dSParshuram Thombare */
1827cc3a392dSParshuram Thombare
1828cc3a392dSParshuram Thombare if (i3cboardinfo->static_addr)
1829cc3a392dSParshuram Thombare i3c_master_early_i3c_dev_add(master, i3cboardinfo);
1830cc3a392dSParshuram Thombare }
18313a379bbcSBoris Brezillon
18323a379bbcSBoris Brezillon ret = i3c_master_do_daa(master);
18333a379bbcSBoris Brezillon if (ret)
18343a379bbcSBoris Brezillon goto err_rstdaa;
18353a379bbcSBoris Brezillon
18363a379bbcSBoris Brezillon return 0;
18373a379bbcSBoris Brezillon
18383a379bbcSBoris Brezillon err_rstdaa:
18393a379bbcSBoris Brezillon i3c_master_rstdaa_locked(master, I3C_BROADCAST_ADDR);
18403a379bbcSBoris Brezillon
18413a379bbcSBoris Brezillon err_bus_cleanup:
18423a379bbcSBoris Brezillon if (master->ops->bus_cleanup)
18433a379bbcSBoris Brezillon master->ops->bus_cleanup(master);
18443a379bbcSBoris Brezillon
18453a379bbcSBoris Brezillon err_detach_devs:
18463a379bbcSBoris Brezillon i3c_master_detach_free_devs(master);
18473a379bbcSBoris Brezillon
18483a379bbcSBoris Brezillon return ret;
18493a379bbcSBoris Brezillon }
18503a379bbcSBoris Brezillon
i3c_master_bus_cleanup(struct i3c_master_controller * master)18513a379bbcSBoris Brezillon static void i3c_master_bus_cleanup(struct i3c_master_controller *master)
18523a379bbcSBoris Brezillon {
18533a379bbcSBoris Brezillon if (master->ops->bus_cleanup)
18543a379bbcSBoris Brezillon master->ops->bus_cleanup(master);
18553a379bbcSBoris Brezillon
18563a379bbcSBoris Brezillon i3c_master_detach_free_devs(master);
18573a379bbcSBoris Brezillon }
18583a379bbcSBoris Brezillon
i3c_master_attach_boardinfo(struct i3c_dev_desc * i3cdev)18599da36a7eSParshuram Thombare static void i3c_master_attach_boardinfo(struct i3c_dev_desc *i3cdev)
18609da36a7eSParshuram Thombare {
18619da36a7eSParshuram Thombare struct i3c_master_controller *master = i3cdev->common.master;
18629da36a7eSParshuram Thombare struct i3c_dev_boardinfo *i3cboardinfo;
18639da36a7eSParshuram Thombare
18649da36a7eSParshuram Thombare list_for_each_entry(i3cboardinfo, &master->boardinfo.i3c, node) {
18659da36a7eSParshuram Thombare if (i3cdev->info.pid != i3cboardinfo->pid)
18669da36a7eSParshuram Thombare continue;
18679da36a7eSParshuram Thombare
18689da36a7eSParshuram Thombare i3cdev->boardinfo = i3cboardinfo;
18699da36a7eSParshuram Thombare i3cdev->info.static_addr = i3cboardinfo->static_addr;
18709da36a7eSParshuram Thombare return;
18719da36a7eSParshuram Thombare }
18729da36a7eSParshuram Thombare }
18739da36a7eSParshuram Thombare
18743a379bbcSBoris Brezillon static struct i3c_dev_desc *
i3c_master_search_i3c_dev_duplicate(struct i3c_dev_desc * refdev)18753a379bbcSBoris Brezillon i3c_master_search_i3c_dev_duplicate(struct i3c_dev_desc *refdev)
18763a379bbcSBoris Brezillon {
1877f12b524eSVitor Soares struct i3c_master_controller *master = i3c_dev_get_master(refdev);
18783a379bbcSBoris Brezillon struct i3c_dev_desc *i3cdev;
18793a379bbcSBoris Brezillon
18803a379bbcSBoris Brezillon i3c_bus_for_each_i3cdev(&master->bus, i3cdev) {
18813a379bbcSBoris Brezillon if (i3cdev != refdev && i3cdev->info.pid == refdev->info.pid)
18823a379bbcSBoris Brezillon return i3cdev;
18833a379bbcSBoris Brezillon }
18843a379bbcSBoris Brezillon
18853a379bbcSBoris Brezillon return NULL;
18863a379bbcSBoris Brezillon }
18873a379bbcSBoris Brezillon
18883a379bbcSBoris Brezillon /**
18893a379bbcSBoris Brezillon * i3c_master_add_i3c_dev_locked() - add an I3C slave to the bus
18903a379bbcSBoris Brezillon * @master: master used to send frames on the bus
18913a379bbcSBoris Brezillon * @addr: I3C slave dynamic address assigned to the device
18923a379bbcSBoris Brezillon *
18933a379bbcSBoris Brezillon * This function is instantiating an I3C device object and adding it to the
18943a379bbcSBoris Brezillon * I3C device list. All device information are automatically retrieved using
18953a379bbcSBoris Brezillon * standard CCC commands.
18963a379bbcSBoris Brezillon *
18973a379bbcSBoris Brezillon * The I3C device object is returned in case the master wants to attach
18983a379bbcSBoris Brezillon * private data to it using i3c_dev_set_master_data().
18993a379bbcSBoris Brezillon *
19003a379bbcSBoris Brezillon * This function must be called with the bus lock held in write mode.
19013a379bbcSBoris Brezillon *
19023a379bbcSBoris Brezillon * Return: a 0 in case of success, an negative error code otherwise.
19033a379bbcSBoris Brezillon */
i3c_master_add_i3c_dev_locked(struct i3c_master_controller * master,u8 addr)19043a379bbcSBoris Brezillon int i3c_master_add_i3c_dev_locked(struct i3c_master_controller *master,
19053a379bbcSBoris Brezillon u8 addr)
19063a379bbcSBoris Brezillon {
19073a379bbcSBoris Brezillon struct i3c_device_info info = { .dyn_addr = addr };
19083a379bbcSBoris Brezillon struct i3c_dev_desc *newdev, *olddev;
19093a379bbcSBoris Brezillon u8 old_dyn_addr = addr, expected_dyn_addr;
19103a379bbcSBoris Brezillon struct i3c_ibi_setup ibireq = { };
19113a379bbcSBoris Brezillon bool enable_ibi = false;
19123a379bbcSBoris Brezillon int ret;
19133a379bbcSBoris Brezillon
19143a379bbcSBoris Brezillon if (!master)
19153a379bbcSBoris Brezillon return -EINVAL;
19163a379bbcSBoris Brezillon
19173a379bbcSBoris Brezillon newdev = i3c_master_alloc_i3c_dev(master, &info);
19183a379bbcSBoris Brezillon if (IS_ERR(newdev))
19193a379bbcSBoris Brezillon return PTR_ERR(newdev);
19203a379bbcSBoris Brezillon
19213a379bbcSBoris Brezillon ret = i3c_master_attach_i3c_dev(master, newdev);
1922840414aeSDan Carpenter if (ret)
19233a379bbcSBoris Brezillon goto err_free_dev;
19243a379bbcSBoris Brezillon
19253a379bbcSBoris Brezillon ret = i3c_master_retrieve_dev_info(newdev);
19263a379bbcSBoris Brezillon if (ret)
1927093c61b6SJisheng Zhang goto err_detach_dev;
19283a379bbcSBoris Brezillon
19299da36a7eSParshuram Thombare i3c_master_attach_boardinfo(newdev);
19309da36a7eSParshuram Thombare
19313a379bbcSBoris Brezillon olddev = i3c_master_search_i3c_dev_duplicate(newdev);
19323a379bbcSBoris Brezillon if (olddev) {
19333a379bbcSBoris Brezillon newdev->dev = olddev->dev;
19343a379bbcSBoris Brezillon if (newdev->dev)
19353a379bbcSBoris Brezillon newdev->dev->desc = newdev;
19363a379bbcSBoris Brezillon
19373a379bbcSBoris Brezillon /*
19383a379bbcSBoris Brezillon * We need to restore the IBI state too, so let's save the
19393a379bbcSBoris Brezillon * IBI information and try to restore them after olddev has
19403a379bbcSBoris Brezillon * been detached+released and its IBI has been stopped and
19413a379bbcSBoris Brezillon * the associated resources have been freed.
19423a379bbcSBoris Brezillon */
19433a379bbcSBoris Brezillon mutex_lock(&olddev->ibi_lock);
19443a379bbcSBoris Brezillon if (olddev->ibi) {
19453a379bbcSBoris Brezillon ibireq.handler = olddev->ibi->handler;
19463a379bbcSBoris Brezillon ibireq.max_payload_len = olddev->ibi->max_payload_len;
19473a379bbcSBoris Brezillon ibireq.num_slots = olddev->ibi->num_slots;
19483a379bbcSBoris Brezillon
19493a379bbcSBoris Brezillon if (olddev->ibi->enabled) {
19503a379bbcSBoris Brezillon enable_ibi = true;
19513a379bbcSBoris Brezillon i3c_dev_disable_ibi_locked(olddev);
19523a379bbcSBoris Brezillon }
19533a379bbcSBoris Brezillon
19543a379bbcSBoris Brezillon i3c_dev_free_ibi_locked(olddev);
19553a379bbcSBoris Brezillon }
19563a379bbcSBoris Brezillon mutex_unlock(&olddev->ibi_lock);
19573a379bbcSBoris Brezillon
19583a379bbcSBoris Brezillon old_dyn_addr = olddev->info.dyn_addr;
19593a379bbcSBoris Brezillon
19603a379bbcSBoris Brezillon i3c_master_detach_i3c_dev(olddev);
19613a379bbcSBoris Brezillon i3c_master_free_i3c_dev(olddev);
19623a379bbcSBoris Brezillon }
19633a379bbcSBoris Brezillon
19643a379bbcSBoris Brezillon /*
19653a379bbcSBoris Brezillon * Depending on our previous state, the expected dynamic address might
19663a379bbcSBoris Brezillon * differ:
19673a379bbcSBoris Brezillon * - if the device already had a dynamic address assigned, let's try to
19683a379bbcSBoris Brezillon * re-apply this one
19693a379bbcSBoris Brezillon * - if the device did not have a dynamic address and the firmware
19703a379bbcSBoris Brezillon * requested a specific address, pick this one
19713a379bbcSBoris Brezillon * - in any other case, keep the address automatically assigned by the
19723a379bbcSBoris Brezillon * master
19733a379bbcSBoris Brezillon */
19743a379bbcSBoris Brezillon if (old_dyn_addr && old_dyn_addr != newdev->info.dyn_addr)
19753a379bbcSBoris Brezillon expected_dyn_addr = old_dyn_addr;
19763a379bbcSBoris Brezillon else if (newdev->boardinfo && newdev->boardinfo->init_dyn_addr)
19773a379bbcSBoris Brezillon expected_dyn_addr = newdev->boardinfo->init_dyn_addr;
19783a379bbcSBoris Brezillon else
19793a379bbcSBoris Brezillon expected_dyn_addr = newdev->info.dyn_addr;
19803a379bbcSBoris Brezillon
19813a379bbcSBoris Brezillon if (newdev->info.dyn_addr != expected_dyn_addr) {
19823a379bbcSBoris Brezillon /*
19833a379bbcSBoris Brezillon * Try to apply the expected dynamic address. If it fails, keep
19843a379bbcSBoris Brezillon * the address assigned by the master.
19853a379bbcSBoris Brezillon */
19863a379bbcSBoris Brezillon ret = i3c_master_setnewda_locked(master,
19873a379bbcSBoris Brezillon newdev->info.dyn_addr,
19883a379bbcSBoris Brezillon expected_dyn_addr);
19893a379bbcSBoris Brezillon if (!ret) {
19903a379bbcSBoris Brezillon old_dyn_addr = newdev->info.dyn_addr;
19913a379bbcSBoris Brezillon newdev->info.dyn_addr = expected_dyn_addr;
19923a379bbcSBoris Brezillon i3c_master_reattach_i3c_dev(newdev, old_dyn_addr);
19933a379bbcSBoris Brezillon } else {
19943a379bbcSBoris Brezillon dev_err(&master->dev,
19953a379bbcSBoris Brezillon "Failed to assign reserved/old address to device %d%llx",
19963a379bbcSBoris Brezillon master->bus.id, newdev->info.pid);
19973a379bbcSBoris Brezillon }
19983a379bbcSBoris Brezillon }
19993a379bbcSBoris Brezillon
20003a379bbcSBoris Brezillon /*
20013a379bbcSBoris Brezillon * Now is time to try to restore the IBI setup. If we're lucky,
20023a379bbcSBoris Brezillon * everything works as before, otherwise, all we can do is complain.
20033a379bbcSBoris Brezillon * FIXME: maybe we should add callback to inform the driver that it
20043a379bbcSBoris Brezillon * should request the IBI again instead of trying to hide that from
20053a379bbcSBoris Brezillon * him.
20063a379bbcSBoris Brezillon */
20073a379bbcSBoris Brezillon if (ibireq.handler) {
20083a379bbcSBoris Brezillon mutex_lock(&newdev->ibi_lock);
20093a379bbcSBoris Brezillon ret = i3c_dev_request_ibi_locked(newdev, &ibireq);
20103a379bbcSBoris Brezillon if (ret) {
20113a379bbcSBoris Brezillon dev_err(&master->dev,
20123a379bbcSBoris Brezillon "Failed to request IBI on device %d-%llx",
20133a379bbcSBoris Brezillon master->bus.id, newdev->info.pid);
20143a379bbcSBoris Brezillon } else if (enable_ibi) {
20153a379bbcSBoris Brezillon ret = i3c_dev_enable_ibi_locked(newdev);
20163a379bbcSBoris Brezillon if (ret)
20173a379bbcSBoris Brezillon dev_err(&master->dev,
20183a379bbcSBoris Brezillon "Failed to re-enable IBI on device %d-%llx",
20193a379bbcSBoris Brezillon master->bus.id, newdev->info.pid);
20203a379bbcSBoris Brezillon }
20213a379bbcSBoris Brezillon mutex_unlock(&newdev->ibi_lock);
20223a379bbcSBoris Brezillon }
20233a379bbcSBoris Brezillon
20243a379bbcSBoris Brezillon return 0;
20253a379bbcSBoris Brezillon
20263a379bbcSBoris Brezillon err_detach_dev:
20273a379bbcSBoris Brezillon if (newdev->dev && newdev->dev->desc)
20283a379bbcSBoris Brezillon newdev->dev->desc = NULL;
20293a379bbcSBoris Brezillon
20303a379bbcSBoris Brezillon i3c_master_detach_i3c_dev(newdev);
20313a379bbcSBoris Brezillon
20323a379bbcSBoris Brezillon err_free_dev:
20333a379bbcSBoris Brezillon i3c_master_free_i3c_dev(newdev);
20343a379bbcSBoris Brezillon
20353a379bbcSBoris Brezillon return ret;
20363a379bbcSBoris Brezillon }
20373a379bbcSBoris Brezillon EXPORT_SYMBOL_GPL(i3c_master_add_i3c_dev_locked);
20383a379bbcSBoris Brezillon
20393a379bbcSBoris Brezillon #define OF_I3C_REG1_IS_I2C_DEV BIT(31)
20403a379bbcSBoris Brezillon
20413a379bbcSBoris Brezillon static int
of_i3c_master_add_i2c_boardinfo(struct i3c_master_controller * master,struct device_node * node,u32 * reg)20423a379bbcSBoris Brezillon of_i3c_master_add_i2c_boardinfo(struct i3c_master_controller *master,
20433a379bbcSBoris Brezillon struct device_node *node, u32 *reg)
20443a379bbcSBoris Brezillon {
20453a379bbcSBoris Brezillon struct i2c_dev_boardinfo *boardinfo;
20463a379bbcSBoris Brezillon struct device *dev = &master->dev;
20473a379bbcSBoris Brezillon int ret;
20483a379bbcSBoris Brezillon
20493a379bbcSBoris Brezillon boardinfo = devm_kzalloc(dev, sizeof(*boardinfo), GFP_KERNEL);
20503a379bbcSBoris Brezillon if (!boardinfo)
20513a379bbcSBoris Brezillon return -ENOMEM;
20523a379bbcSBoris Brezillon
20533a379bbcSBoris Brezillon ret = of_i2c_get_board_info(dev, node, &boardinfo->base);
20543a379bbcSBoris Brezillon if (ret)
20553a379bbcSBoris Brezillon return ret;
20563a379bbcSBoris Brezillon
205788c50322SPrzemyslaw Gaj /*
205888c50322SPrzemyslaw Gaj * The I3C Specification does not clearly say I2C devices with 10-bit
205988c50322SPrzemyslaw Gaj * address are supported. These devices can't be passed properly through
206088c50322SPrzemyslaw Gaj * DEFSLVS command.
206188c50322SPrzemyslaw Gaj */
206288c50322SPrzemyslaw Gaj if (boardinfo->base.flags & I2C_CLIENT_TEN) {
2063de896499SWolfram Sang dev_err(dev, "I2C device with 10 bit address not supported.");
206488c50322SPrzemyslaw Gaj return -ENOTSUPP;
206588c50322SPrzemyslaw Gaj }
206688c50322SPrzemyslaw Gaj
20673a379bbcSBoris Brezillon /* LVR is encoded in reg[2]. */
20683a379bbcSBoris Brezillon boardinfo->lvr = reg[2];
20693a379bbcSBoris Brezillon
20703a379bbcSBoris Brezillon list_add_tail(&boardinfo->node, &master->boardinfo.i2c);
20713a379bbcSBoris Brezillon of_node_get(node);
20723a379bbcSBoris Brezillon
20733a379bbcSBoris Brezillon return 0;
20743a379bbcSBoris Brezillon }
20753a379bbcSBoris Brezillon
20763a379bbcSBoris Brezillon static int
of_i3c_master_add_i3c_boardinfo(struct i3c_master_controller * master,struct device_node * node,u32 * reg)20773a379bbcSBoris Brezillon of_i3c_master_add_i3c_boardinfo(struct i3c_master_controller *master,
20783a379bbcSBoris Brezillon struct device_node *node, u32 *reg)
20793a379bbcSBoris Brezillon {
20803a379bbcSBoris Brezillon struct i3c_dev_boardinfo *boardinfo;
20813a379bbcSBoris Brezillon struct device *dev = &master->dev;
20823a379bbcSBoris Brezillon enum i3c_addr_slot_status addrstatus;
20833a379bbcSBoris Brezillon u32 init_dyn_addr = 0;
20843a379bbcSBoris Brezillon
20853a379bbcSBoris Brezillon boardinfo = devm_kzalloc(dev, sizeof(*boardinfo), GFP_KERNEL);
20863a379bbcSBoris Brezillon if (!boardinfo)
20873a379bbcSBoris Brezillon return -ENOMEM;
20883a379bbcSBoris Brezillon
20893a379bbcSBoris Brezillon if (reg[0]) {
20903a379bbcSBoris Brezillon if (reg[0] > I3C_MAX_ADDR)
20913a379bbcSBoris Brezillon return -EINVAL;
20923a379bbcSBoris Brezillon
20933a379bbcSBoris Brezillon addrstatus = i3c_bus_get_addr_slot_status(&master->bus,
20943a379bbcSBoris Brezillon reg[0]);
20953a379bbcSBoris Brezillon if (addrstatus != I3C_ADDR_SLOT_FREE)
20963a379bbcSBoris Brezillon return -EINVAL;
20973a379bbcSBoris Brezillon }
20983a379bbcSBoris Brezillon
20993a379bbcSBoris Brezillon boardinfo->static_addr = reg[0];
21003a379bbcSBoris Brezillon
21013a379bbcSBoris Brezillon if (!of_property_read_u32(node, "assigned-address", &init_dyn_addr)) {
21023a379bbcSBoris Brezillon if (init_dyn_addr > I3C_MAX_ADDR)
21033a379bbcSBoris Brezillon return -EINVAL;
21043a379bbcSBoris Brezillon
21053a379bbcSBoris Brezillon addrstatus = i3c_bus_get_addr_slot_status(&master->bus,
21063a379bbcSBoris Brezillon init_dyn_addr);
21073a379bbcSBoris Brezillon if (addrstatus != I3C_ADDR_SLOT_FREE)
21083a379bbcSBoris Brezillon return -EINVAL;
21093a379bbcSBoris Brezillon }
21103a379bbcSBoris Brezillon
21113a379bbcSBoris Brezillon boardinfo->pid = ((u64)reg[1] << 32) | reg[2];
21123a379bbcSBoris Brezillon
21139752c37cSVitor Soares if ((boardinfo->pid & GENMASK_ULL(63, 48)) ||
21149752c37cSVitor Soares I3C_PID_RND_LOWER_32BITS(boardinfo->pid))
21153a379bbcSBoris Brezillon return -EINVAL;
21163a379bbcSBoris Brezillon
21173a379bbcSBoris Brezillon boardinfo->init_dyn_addr = init_dyn_addr;
21183a379bbcSBoris Brezillon boardinfo->of_node = of_node_get(node);
21193a379bbcSBoris Brezillon list_add_tail(&boardinfo->node, &master->boardinfo.i3c);
21203a379bbcSBoris Brezillon
21213a379bbcSBoris Brezillon return 0;
21223a379bbcSBoris Brezillon }
21233a379bbcSBoris Brezillon
of_i3c_master_add_dev(struct i3c_master_controller * master,struct device_node * node)21243a379bbcSBoris Brezillon static int of_i3c_master_add_dev(struct i3c_master_controller *master,
21253a379bbcSBoris Brezillon struct device_node *node)
21263a379bbcSBoris Brezillon {
21273a379bbcSBoris Brezillon u32 reg[3];
21283a379bbcSBoris Brezillon int ret;
21293a379bbcSBoris Brezillon
21303a379bbcSBoris Brezillon if (!master || !node)
21313a379bbcSBoris Brezillon return -EINVAL;
21323a379bbcSBoris Brezillon
21333a379bbcSBoris Brezillon ret = of_property_read_u32_array(node, "reg", reg, ARRAY_SIZE(reg));
21343a379bbcSBoris Brezillon if (ret)
21353a379bbcSBoris Brezillon return ret;
21363a379bbcSBoris Brezillon
21373a379bbcSBoris Brezillon /*
21383a379bbcSBoris Brezillon * The manufacturer ID can't be 0. If reg[1] == 0 that means we're
21393a379bbcSBoris Brezillon * dealing with an I2C device.
21403a379bbcSBoris Brezillon */
21413a379bbcSBoris Brezillon if (!reg[1])
21423a379bbcSBoris Brezillon ret = of_i3c_master_add_i2c_boardinfo(master, node, reg);
21433a379bbcSBoris Brezillon else
21443a379bbcSBoris Brezillon ret = of_i3c_master_add_i3c_boardinfo(master, node, reg);
21453a379bbcSBoris Brezillon
21463a379bbcSBoris Brezillon return ret;
21473a379bbcSBoris Brezillon }
21483a379bbcSBoris Brezillon
of_populate_i3c_bus(struct i3c_master_controller * master)21493a379bbcSBoris Brezillon static int of_populate_i3c_bus(struct i3c_master_controller *master)
21503a379bbcSBoris Brezillon {
21513a379bbcSBoris Brezillon struct device *dev = &master->dev;
21523a379bbcSBoris Brezillon struct device_node *i3cbus_np = dev->of_node;
21533a379bbcSBoris Brezillon struct device_node *node;
21543a379bbcSBoris Brezillon int ret;
21553a379bbcSBoris Brezillon u32 val;
21563a379bbcSBoris Brezillon
21573a379bbcSBoris Brezillon if (!i3cbus_np)
21583a379bbcSBoris Brezillon return 0;
21593a379bbcSBoris Brezillon
21603a379bbcSBoris Brezillon for_each_available_child_of_node(i3cbus_np, node) {
21613a379bbcSBoris Brezillon ret = of_i3c_master_add_dev(master, node);
216291227632SNishka Dasgupta if (ret) {
216391227632SNishka Dasgupta of_node_put(node);
21643a379bbcSBoris Brezillon return ret;
21653a379bbcSBoris Brezillon }
216691227632SNishka Dasgupta }
21673a379bbcSBoris Brezillon
21683a379bbcSBoris Brezillon /*
21693a379bbcSBoris Brezillon * The user might want to limit I2C and I3C speed in case some devices
21703a379bbcSBoris Brezillon * on the bus are not supporting typical rates, or if the bus topology
21713a379bbcSBoris Brezillon * prevents it from using max possible rate.
21723a379bbcSBoris Brezillon */
21733a379bbcSBoris Brezillon if (!of_property_read_u32(i3cbus_np, "i2c-scl-hz", &val))
21743a379bbcSBoris Brezillon master->bus.scl_rate.i2c = val;
21753a379bbcSBoris Brezillon
21763a379bbcSBoris Brezillon if (!of_property_read_u32(i3cbus_np, "i3c-scl-hz", &val))
21773a379bbcSBoris Brezillon master->bus.scl_rate.i3c = val;
21783a379bbcSBoris Brezillon
21793a379bbcSBoris Brezillon return 0;
21803a379bbcSBoris Brezillon }
21813a379bbcSBoris Brezillon
i3c_master_i2c_adapter_xfer(struct i2c_adapter * adap,struct i2c_msg * xfers,int nxfers)21823a379bbcSBoris Brezillon static int i3c_master_i2c_adapter_xfer(struct i2c_adapter *adap,
21833a379bbcSBoris Brezillon struct i2c_msg *xfers, int nxfers)
21843a379bbcSBoris Brezillon {
21853a379bbcSBoris Brezillon struct i3c_master_controller *master = i2c_adapter_to_i3c_master(adap);
21863a379bbcSBoris Brezillon struct i2c_dev_desc *dev;
21873a379bbcSBoris Brezillon int i, ret;
21883a379bbcSBoris Brezillon u16 addr;
21893a379bbcSBoris Brezillon
21903a379bbcSBoris Brezillon if (!xfers || !master || nxfers <= 0)
21913a379bbcSBoris Brezillon return -EINVAL;
21923a379bbcSBoris Brezillon
21933a379bbcSBoris Brezillon if (!master->ops->i2c_xfers)
21943a379bbcSBoris Brezillon return -ENOTSUPP;
21953a379bbcSBoris Brezillon
21963a379bbcSBoris Brezillon /* Doing transfers to different devices is not supported. */
21973a379bbcSBoris Brezillon addr = xfers[0].addr;
21983a379bbcSBoris Brezillon for (i = 1; i < nxfers; i++) {
21993a379bbcSBoris Brezillon if (addr != xfers[i].addr)
22003a379bbcSBoris Brezillon return -ENOTSUPP;
22013a379bbcSBoris Brezillon }
22023a379bbcSBoris Brezillon
22033a379bbcSBoris Brezillon i3c_bus_normaluse_lock(&master->bus);
22043a379bbcSBoris Brezillon dev = i3c_master_find_i2c_dev_by_addr(master, addr);
22053a379bbcSBoris Brezillon if (!dev)
22063a379bbcSBoris Brezillon ret = -ENOENT;
22073a379bbcSBoris Brezillon else
22083a379bbcSBoris Brezillon ret = master->ops->i2c_xfers(dev, xfers, nxfers);
22093a379bbcSBoris Brezillon i3c_bus_normaluse_unlock(&master->bus);
22103a379bbcSBoris Brezillon
22113a379bbcSBoris Brezillon return ret ? ret : nxfers;
22123a379bbcSBoris Brezillon }
22133a379bbcSBoris Brezillon
i3c_master_i2c_funcs(struct i2c_adapter * adapter)221488c50322SPrzemyslaw Gaj static u32 i3c_master_i2c_funcs(struct i2c_adapter *adapter)
22153a379bbcSBoris Brezillon {
221688c50322SPrzemyslaw Gaj return I2C_FUNC_SMBUS_EMUL | I2C_FUNC_I2C;
22173a379bbcSBoris Brezillon }
22183a379bbcSBoris Brezillon
i3c_master_i2c_get_lvr(struct i2c_client * client)221972a4501bSJamie Iles static u8 i3c_master_i2c_get_lvr(struct i2c_client *client)
222072a4501bSJamie Iles {
222172a4501bSJamie Iles /* Fall back to no spike filters and FM bus mode. */
222272a4501bSJamie Iles u8 lvr = I3C_LVR_I2C_INDEX(2) | I3C_LVR_I2C_FM_MODE;
222372a4501bSJamie Iles
222472a4501bSJamie Iles if (client->dev.of_node) {
222572a4501bSJamie Iles u32 reg[3];
222672a4501bSJamie Iles
222772a4501bSJamie Iles if (!of_property_read_u32_array(client->dev.of_node, "reg",
222872a4501bSJamie Iles reg, ARRAY_SIZE(reg)))
222972a4501bSJamie Iles lvr = reg[2];
223072a4501bSJamie Iles }
223172a4501bSJamie Iles
223272a4501bSJamie Iles return lvr;
223372a4501bSJamie Iles }
223472a4501bSJamie Iles
i3c_master_i2c_attach(struct i2c_adapter * adap,struct i2c_client * client)223572a4501bSJamie Iles static int i3c_master_i2c_attach(struct i2c_adapter *adap, struct i2c_client *client)
223672a4501bSJamie Iles {
223772a4501bSJamie Iles struct i3c_master_controller *master = i2c_adapter_to_i3c_master(adap);
223872a4501bSJamie Iles enum i3c_addr_slot_status status;
223972a4501bSJamie Iles struct i2c_dev_desc *i2cdev;
224072a4501bSJamie Iles int ret;
224172a4501bSJamie Iles
224272a4501bSJamie Iles /* Already added by board info? */
224372a4501bSJamie Iles if (i3c_master_find_i2c_dev_by_addr(master, client->addr))
224472a4501bSJamie Iles return 0;
224572a4501bSJamie Iles
224672a4501bSJamie Iles status = i3c_bus_get_addr_slot_status(&master->bus, client->addr);
224772a4501bSJamie Iles if (status != I3C_ADDR_SLOT_FREE)
224872a4501bSJamie Iles return -EBUSY;
224972a4501bSJamie Iles
225072a4501bSJamie Iles i3c_bus_set_addr_slot_status(&master->bus, client->addr,
225172a4501bSJamie Iles I3C_ADDR_SLOT_I2C_DEV);
225272a4501bSJamie Iles
225372a4501bSJamie Iles i2cdev = i3c_master_alloc_i2c_dev(master, client->addr,
225472a4501bSJamie Iles i3c_master_i2c_get_lvr(client));
225572a4501bSJamie Iles if (IS_ERR(i2cdev)) {
225672a4501bSJamie Iles ret = PTR_ERR(i2cdev);
225772a4501bSJamie Iles goto out_clear_status;
225872a4501bSJamie Iles }
225972a4501bSJamie Iles
226072a4501bSJamie Iles ret = i3c_master_attach_i2c_dev(master, i2cdev);
226172a4501bSJamie Iles if (ret)
226272a4501bSJamie Iles goto out_free_dev;
226372a4501bSJamie Iles
226472a4501bSJamie Iles return 0;
226572a4501bSJamie Iles
226672a4501bSJamie Iles out_free_dev:
226772a4501bSJamie Iles i3c_master_free_i2c_dev(i2cdev);
226872a4501bSJamie Iles out_clear_status:
226972a4501bSJamie Iles i3c_bus_set_addr_slot_status(&master->bus, client->addr,
227072a4501bSJamie Iles I3C_ADDR_SLOT_FREE);
227172a4501bSJamie Iles
227272a4501bSJamie Iles return ret;
227372a4501bSJamie Iles }
227472a4501bSJamie Iles
i3c_master_i2c_detach(struct i2c_adapter * adap,struct i2c_client * client)227572a4501bSJamie Iles static int i3c_master_i2c_detach(struct i2c_adapter *adap, struct i2c_client *client)
227672a4501bSJamie Iles {
227772a4501bSJamie Iles struct i3c_master_controller *master = i2c_adapter_to_i3c_master(adap);
227872a4501bSJamie Iles struct i2c_dev_desc *dev;
227972a4501bSJamie Iles
228072a4501bSJamie Iles dev = i3c_master_find_i2c_dev_by_addr(master, client->addr);
228172a4501bSJamie Iles if (!dev)
228272a4501bSJamie Iles return -ENODEV;
228372a4501bSJamie Iles
228472a4501bSJamie Iles i3c_master_detach_i2c_dev(dev);
228572a4501bSJamie Iles i3c_bus_set_addr_slot_status(&master->bus, dev->addr,
228672a4501bSJamie Iles I3C_ADDR_SLOT_FREE);
228772a4501bSJamie Iles i3c_master_free_i2c_dev(dev);
228872a4501bSJamie Iles
228972a4501bSJamie Iles return 0;
229072a4501bSJamie Iles }
229172a4501bSJamie Iles
22923a379bbcSBoris Brezillon static const struct i2c_algorithm i3c_master_i2c_algo = {
22933a379bbcSBoris Brezillon .master_xfer = i3c_master_i2c_adapter_xfer,
229488c50322SPrzemyslaw Gaj .functionality = i3c_master_i2c_funcs,
22953a379bbcSBoris Brezillon };
22963a379bbcSBoris Brezillon
i3c_i2c_notifier_call(struct notifier_block * nb,unsigned long action,void * data)229772a4501bSJamie Iles static int i3c_i2c_notifier_call(struct notifier_block *nb, unsigned long action,
229872a4501bSJamie Iles void *data)
229972a4501bSJamie Iles {
230072a4501bSJamie Iles struct i2c_adapter *adap;
230172a4501bSJamie Iles struct i2c_client *client;
230272a4501bSJamie Iles struct device *dev = data;
230372a4501bSJamie Iles struct i3c_master_controller *master;
230472a4501bSJamie Iles int ret;
230572a4501bSJamie Iles
230672a4501bSJamie Iles if (dev->type != &i2c_client_type)
230772a4501bSJamie Iles return 0;
230872a4501bSJamie Iles
230972a4501bSJamie Iles client = to_i2c_client(dev);
231072a4501bSJamie Iles adap = client->adapter;
231172a4501bSJamie Iles
231272a4501bSJamie Iles if (adap->algo != &i3c_master_i2c_algo)
231372a4501bSJamie Iles return 0;
231472a4501bSJamie Iles
231572a4501bSJamie Iles master = i2c_adapter_to_i3c_master(adap);
231672a4501bSJamie Iles
231772a4501bSJamie Iles i3c_bus_maintenance_lock(&master->bus);
231872a4501bSJamie Iles switch (action) {
231972a4501bSJamie Iles case BUS_NOTIFY_ADD_DEVICE:
232072a4501bSJamie Iles ret = i3c_master_i2c_attach(adap, client);
232172a4501bSJamie Iles break;
232272a4501bSJamie Iles case BUS_NOTIFY_DEL_DEVICE:
232372a4501bSJamie Iles ret = i3c_master_i2c_detach(adap, client);
232472a4501bSJamie Iles break;
232572a4501bSJamie Iles }
232672a4501bSJamie Iles i3c_bus_maintenance_unlock(&master->bus);
232772a4501bSJamie Iles
232872a4501bSJamie Iles return ret;
232972a4501bSJamie Iles }
233072a4501bSJamie Iles
233172a4501bSJamie Iles static struct notifier_block i2cdev_notifier = {
233272a4501bSJamie Iles .notifier_call = i3c_i2c_notifier_call,
233372a4501bSJamie Iles };
233472a4501bSJamie Iles
i3c_master_i2c_adapter_init(struct i3c_master_controller * master)23353a379bbcSBoris Brezillon static int i3c_master_i2c_adapter_init(struct i3c_master_controller *master)
23363a379bbcSBoris Brezillon {
23373a379bbcSBoris Brezillon struct i2c_adapter *adap = i3c_master_to_i2c_adapter(master);
23383a379bbcSBoris Brezillon struct i2c_dev_desc *i2cdev;
233931b9887cSJamie Iles struct i2c_dev_boardinfo *i2cboardinfo;
23403a379bbcSBoris Brezillon int ret;
23413a379bbcSBoris Brezillon
23423a379bbcSBoris Brezillon adap->dev.parent = master->dev.parent;
23433a379bbcSBoris Brezillon adap->owner = master->dev.parent->driver->owner;
23443a379bbcSBoris Brezillon adap->algo = &i3c_master_i2c_algo;
23453a379bbcSBoris Brezillon strncpy(adap->name, dev_name(master->dev.parent), sizeof(adap->name));
23463a379bbcSBoris Brezillon
23473a379bbcSBoris Brezillon /* FIXME: Should we allow i3c masters to override these values? */
23483a379bbcSBoris Brezillon adap->timeout = 1000;
23493a379bbcSBoris Brezillon adap->retries = 3;
23503a379bbcSBoris Brezillon
23513a379bbcSBoris Brezillon ret = i2c_add_adapter(adap);
23523a379bbcSBoris Brezillon if (ret)
23533a379bbcSBoris Brezillon return ret;
23543a379bbcSBoris Brezillon
23553a379bbcSBoris Brezillon /*
23563a379bbcSBoris Brezillon * We silently ignore failures here. The bus should keep working
23573a379bbcSBoris Brezillon * correctly even if one or more i2c devices are not registered.
23583a379bbcSBoris Brezillon */
23596cbf8b38SJamie Iles list_for_each_entry(i2cboardinfo, &master->boardinfo.i2c, node) {
23606cbf8b38SJamie Iles i2cdev = i3c_master_find_i2c_dev_by_addr(master,
23616cbf8b38SJamie Iles i2cboardinfo->base.addr);
23626cbf8b38SJamie Iles if (WARN_ON(!i2cdev))
23636cbf8b38SJamie Iles continue;
236431b9887cSJamie Iles i2cdev->dev = i2c_new_client_device(adap, &i2cboardinfo->base);
23656cbf8b38SJamie Iles }
23663a379bbcSBoris Brezillon
23673a379bbcSBoris Brezillon return 0;
23683a379bbcSBoris Brezillon }
23693a379bbcSBoris Brezillon
i3c_master_i2c_adapter_cleanup(struct i3c_master_controller * master)23703a379bbcSBoris Brezillon static void i3c_master_i2c_adapter_cleanup(struct i3c_master_controller *master)
23713a379bbcSBoris Brezillon {
23723a379bbcSBoris Brezillon struct i2c_dev_desc *i2cdev;
23733a379bbcSBoris Brezillon
23743a379bbcSBoris Brezillon i2c_del_adapter(&master->i2c);
23753a379bbcSBoris Brezillon
23763a379bbcSBoris Brezillon i3c_bus_for_each_i2cdev(&master->bus, i2cdev)
23773a379bbcSBoris Brezillon i2cdev->dev = NULL;
23783a379bbcSBoris Brezillon }
23793a379bbcSBoris Brezillon
i3c_master_unregister_i3c_devs(struct i3c_master_controller * master)23803a379bbcSBoris Brezillon static void i3c_master_unregister_i3c_devs(struct i3c_master_controller *master)
23813a379bbcSBoris Brezillon {
23823a379bbcSBoris Brezillon struct i3c_dev_desc *i3cdev;
23833a379bbcSBoris Brezillon
23843a379bbcSBoris Brezillon i3c_bus_for_each_i3cdev(&master->bus, i3cdev) {
23853a379bbcSBoris Brezillon if (!i3cdev->dev)
23863a379bbcSBoris Brezillon continue;
23873a379bbcSBoris Brezillon
23883a379bbcSBoris Brezillon i3cdev->dev->desc = NULL;
23893a379bbcSBoris Brezillon if (device_is_registered(&i3cdev->dev->dev))
23903a379bbcSBoris Brezillon device_unregister(&i3cdev->dev->dev);
23913a379bbcSBoris Brezillon else
23923a379bbcSBoris Brezillon put_device(&i3cdev->dev->dev);
23933a379bbcSBoris Brezillon i3cdev->dev = NULL;
23943a379bbcSBoris Brezillon }
23953a379bbcSBoris Brezillon }
23963a379bbcSBoris Brezillon
23973a379bbcSBoris Brezillon /**
23983a379bbcSBoris Brezillon * i3c_master_queue_ibi() - Queue an IBI
23993a379bbcSBoris Brezillon * @dev: the device this IBI is coming from
24003a379bbcSBoris Brezillon * @slot: the IBI slot used to store the payload
24013a379bbcSBoris Brezillon *
24023a379bbcSBoris Brezillon * Queue an IBI to the controller workqueue. The IBI handler attached to
24033a379bbcSBoris Brezillon * the dev will be called from a workqueue context.
24043a379bbcSBoris Brezillon */
i3c_master_queue_ibi(struct i3c_dev_desc * dev,struct i3c_ibi_slot * slot)24053a379bbcSBoris Brezillon void i3c_master_queue_ibi(struct i3c_dev_desc *dev, struct i3c_ibi_slot *slot)
24063a379bbcSBoris Brezillon {
24073a379bbcSBoris Brezillon atomic_inc(&dev->ibi->pending_ibis);
24083a379bbcSBoris Brezillon queue_work(dev->common.master->wq, &slot->work);
24093a379bbcSBoris Brezillon }
24103a379bbcSBoris Brezillon EXPORT_SYMBOL_GPL(i3c_master_queue_ibi);
24113a379bbcSBoris Brezillon
i3c_master_handle_ibi(struct work_struct * work)24123a379bbcSBoris Brezillon static void i3c_master_handle_ibi(struct work_struct *work)
24133a379bbcSBoris Brezillon {
24143a379bbcSBoris Brezillon struct i3c_ibi_slot *slot = container_of(work, struct i3c_ibi_slot,
24153a379bbcSBoris Brezillon work);
24163a379bbcSBoris Brezillon struct i3c_dev_desc *dev = slot->dev;
24173a379bbcSBoris Brezillon struct i3c_master_controller *master = i3c_dev_get_master(dev);
24183a379bbcSBoris Brezillon struct i3c_ibi_payload payload;
24193a379bbcSBoris Brezillon
24203a379bbcSBoris Brezillon payload.data = slot->data;
24213a379bbcSBoris Brezillon payload.len = slot->len;
24223a379bbcSBoris Brezillon
24233a379bbcSBoris Brezillon if (dev->dev)
24243a379bbcSBoris Brezillon dev->ibi->handler(dev->dev, &payload);
24253a379bbcSBoris Brezillon
24263a379bbcSBoris Brezillon master->ops->recycle_ibi_slot(dev, slot);
24273a379bbcSBoris Brezillon if (atomic_dec_and_test(&dev->ibi->pending_ibis))
24283a379bbcSBoris Brezillon complete(&dev->ibi->all_ibis_handled);
24293a379bbcSBoris Brezillon }
24303a379bbcSBoris Brezillon
i3c_master_init_ibi_slot(struct i3c_dev_desc * dev,struct i3c_ibi_slot * slot)24313a379bbcSBoris Brezillon static void i3c_master_init_ibi_slot(struct i3c_dev_desc *dev,
24323a379bbcSBoris Brezillon struct i3c_ibi_slot *slot)
24333a379bbcSBoris Brezillon {
24343a379bbcSBoris Brezillon slot->dev = dev;
24353a379bbcSBoris Brezillon INIT_WORK(&slot->work, i3c_master_handle_ibi);
24363a379bbcSBoris Brezillon }
24373a379bbcSBoris Brezillon
24383a379bbcSBoris Brezillon struct i3c_generic_ibi_slot {
24393a379bbcSBoris Brezillon struct list_head node;
24403a379bbcSBoris Brezillon struct i3c_ibi_slot base;
24413a379bbcSBoris Brezillon };
24423a379bbcSBoris Brezillon
24433a379bbcSBoris Brezillon struct i3c_generic_ibi_pool {
24443a379bbcSBoris Brezillon spinlock_t lock;
24453a379bbcSBoris Brezillon unsigned int num_slots;
24463a379bbcSBoris Brezillon struct i3c_generic_ibi_slot *slots;
24473a379bbcSBoris Brezillon void *payload_buf;
24483a379bbcSBoris Brezillon struct list_head free_slots;
24493a379bbcSBoris Brezillon struct list_head pending;
24503a379bbcSBoris Brezillon };
24513a379bbcSBoris Brezillon
24523a379bbcSBoris Brezillon /**
24533a379bbcSBoris Brezillon * i3c_generic_ibi_free_pool() - Free a generic IBI pool
24543a379bbcSBoris Brezillon * @pool: the IBI pool to free
24553a379bbcSBoris Brezillon *
24563a379bbcSBoris Brezillon * Free all IBI slots allated by a generic IBI pool.
24573a379bbcSBoris Brezillon */
i3c_generic_ibi_free_pool(struct i3c_generic_ibi_pool * pool)24583a379bbcSBoris Brezillon void i3c_generic_ibi_free_pool(struct i3c_generic_ibi_pool *pool)
24593a379bbcSBoris Brezillon {
24603a379bbcSBoris Brezillon struct i3c_generic_ibi_slot *slot;
24613a379bbcSBoris Brezillon unsigned int nslots = 0;
24623a379bbcSBoris Brezillon
24633a379bbcSBoris Brezillon while (!list_empty(&pool->free_slots)) {
24643a379bbcSBoris Brezillon slot = list_first_entry(&pool->free_slots,
24653a379bbcSBoris Brezillon struct i3c_generic_ibi_slot, node);
24663a379bbcSBoris Brezillon list_del(&slot->node);
24673a379bbcSBoris Brezillon nslots++;
24683a379bbcSBoris Brezillon }
24693a379bbcSBoris Brezillon
24703a379bbcSBoris Brezillon /*
24713a379bbcSBoris Brezillon * If the number of freed slots is not equal to the number of allocated
24723a379bbcSBoris Brezillon * slots we have a leak somewhere.
24733a379bbcSBoris Brezillon */
24743a379bbcSBoris Brezillon WARN_ON(nslots != pool->num_slots);
24753a379bbcSBoris Brezillon
24763a379bbcSBoris Brezillon kfree(pool->payload_buf);
24773a379bbcSBoris Brezillon kfree(pool->slots);
24783a379bbcSBoris Brezillon kfree(pool);
24793a379bbcSBoris Brezillon }
24803a379bbcSBoris Brezillon EXPORT_SYMBOL_GPL(i3c_generic_ibi_free_pool);
24813a379bbcSBoris Brezillon
24823a379bbcSBoris Brezillon /**
24833a379bbcSBoris Brezillon * i3c_generic_ibi_alloc_pool() - Create a generic IBI pool
24843a379bbcSBoris Brezillon * @dev: the device this pool will be used for
24853a379bbcSBoris Brezillon * @req: IBI setup request describing what the device driver expects
24863a379bbcSBoris Brezillon *
24873a379bbcSBoris Brezillon * Create a generic IBI pool based on the information provided in @req.
24883a379bbcSBoris Brezillon *
24893a379bbcSBoris Brezillon * Return: a valid IBI pool in case of success, an ERR_PTR() otherwise.
24903a379bbcSBoris Brezillon */
24913a379bbcSBoris Brezillon struct i3c_generic_ibi_pool *
i3c_generic_ibi_alloc_pool(struct i3c_dev_desc * dev,const struct i3c_ibi_setup * req)24923a379bbcSBoris Brezillon i3c_generic_ibi_alloc_pool(struct i3c_dev_desc *dev,
24933a379bbcSBoris Brezillon const struct i3c_ibi_setup *req)
24943a379bbcSBoris Brezillon {
24953a379bbcSBoris Brezillon struct i3c_generic_ibi_pool *pool;
24963a379bbcSBoris Brezillon struct i3c_generic_ibi_slot *slot;
24973a379bbcSBoris Brezillon unsigned int i;
24983a379bbcSBoris Brezillon int ret;
24993a379bbcSBoris Brezillon
25003a379bbcSBoris Brezillon pool = kzalloc(sizeof(*pool), GFP_KERNEL);
25013a379bbcSBoris Brezillon if (!pool)
25023a379bbcSBoris Brezillon return ERR_PTR(-ENOMEM);
25033a379bbcSBoris Brezillon
25043a379bbcSBoris Brezillon spin_lock_init(&pool->lock);
25053a379bbcSBoris Brezillon INIT_LIST_HEAD(&pool->free_slots);
25063a379bbcSBoris Brezillon INIT_LIST_HEAD(&pool->pending);
25073a379bbcSBoris Brezillon
25083a379bbcSBoris Brezillon pool->slots = kcalloc(req->num_slots, sizeof(*slot), GFP_KERNEL);
25093a379bbcSBoris Brezillon if (!pool->slots) {
25103a379bbcSBoris Brezillon ret = -ENOMEM;
25113a379bbcSBoris Brezillon goto err_free_pool;
25123a379bbcSBoris Brezillon }
25133a379bbcSBoris Brezillon
25143a379bbcSBoris Brezillon if (req->max_payload_len) {
25153a379bbcSBoris Brezillon pool->payload_buf = kcalloc(req->num_slots,
25163a379bbcSBoris Brezillon req->max_payload_len, GFP_KERNEL);
25173a379bbcSBoris Brezillon if (!pool->payload_buf) {
25183a379bbcSBoris Brezillon ret = -ENOMEM;
25193a379bbcSBoris Brezillon goto err_free_pool;
25203a379bbcSBoris Brezillon }
25213a379bbcSBoris Brezillon }
25223a379bbcSBoris Brezillon
25233a379bbcSBoris Brezillon for (i = 0; i < req->num_slots; i++) {
25243a379bbcSBoris Brezillon slot = &pool->slots[i];
25253a379bbcSBoris Brezillon i3c_master_init_ibi_slot(dev, &slot->base);
25263a379bbcSBoris Brezillon
25273a379bbcSBoris Brezillon if (req->max_payload_len)
25283a379bbcSBoris Brezillon slot->base.data = pool->payload_buf +
25293a379bbcSBoris Brezillon (i * req->max_payload_len);
25303a379bbcSBoris Brezillon
25313a379bbcSBoris Brezillon list_add_tail(&slot->node, &pool->free_slots);
25323a379bbcSBoris Brezillon pool->num_slots++;
25333a379bbcSBoris Brezillon }
25343a379bbcSBoris Brezillon
25353a379bbcSBoris Brezillon return pool;
25363a379bbcSBoris Brezillon
25373a379bbcSBoris Brezillon err_free_pool:
25383a379bbcSBoris Brezillon i3c_generic_ibi_free_pool(pool);
25393a379bbcSBoris Brezillon return ERR_PTR(ret);
25403a379bbcSBoris Brezillon }
25413a379bbcSBoris Brezillon EXPORT_SYMBOL_GPL(i3c_generic_ibi_alloc_pool);
25423a379bbcSBoris Brezillon
25433a379bbcSBoris Brezillon /**
25443a379bbcSBoris Brezillon * i3c_generic_ibi_get_free_slot() - Get a free slot from a generic IBI pool
25453a379bbcSBoris Brezillon * @pool: the pool to query an IBI slot on
25463a379bbcSBoris Brezillon *
25473a379bbcSBoris Brezillon * Search for a free slot in a generic IBI pool.
25483a379bbcSBoris Brezillon * The slot should be returned to the pool using i3c_generic_ibi_recycle_slot()
25493a379bbcSBoris Brezillon * when it's no longer needed.
25503a379bbcSBoris Brezillon *
25513a379bbcSBoris Brezillon * Return: a pointer to a free slot, or NULL if there's no free slot available.
25523a379bbcSBoris Brezillon */
25533a379bbcSBoris Brezillon struct i3c_ibi_slot *
i3c_generic_ibi_get_free_slot(struct i3c_generic_ibi_pool * pool)25543a379bbcSBoris Brezillon i3c_generic_ibi_get_free_slot(struct i3c_generic_ibi_pool *pool)
25553a379bbcSBoris Brezillon {
25563a379bbcSBoris Brezillon struct i3c_generic_ibi_slot *slot;
25573a379bbcSBoris Brezillon unsigned long flags;
25583a379bbcSBoris Brezillon
25593a379bbcSBoris Brezillon spin_lock_irqsave(&pool->lock, flags);
25603a379bbcSBoris Brezillon slot = list_first_entry_or_null(&pool->free_slots,
25613a379bbcSBoris Brezillon struct i3c_generic_ibi_slot, node);
25623a379bbcSBoris Brezillon if (slot)
25633a379bbcSBoris Brezillon list_del(&slot->node);
25643a379bbcSBoris Brezillon spin_unlock_irqrestore(&pool->lock, flags);
25653a379bbcSBoris Brezillon
25663a379bbcSBoris Brezillon return slot ? &slot->base : NULL;
25673a379bbcSBoris Brezillon }
25683a379bbcSBoris Brezillon EXPORT_SYMBOL_GPL(i3c_generic_ibi_get_free_slot);
25693a379bbcSBoris Brezillon
25703a379bbcSBoris Brezillon /**
25713a379bbcSBoris Brezillon * i3c_generic_ibi_recycle_slot() - Return a slot to a generic IBI pool
25723a379bbcSBoris Brezillon * @pool: the pool to return the IBI slot to
25733a379bbcSBoris Brezillon * @s: IBI slot to recycle
25743a379bbcSBoris Brezillon *
25753a379bbcSBoris Brezillon * Add an IBI slot back to its generic IBI pool. Should be called from the
25763a379bbcSBoris Brezillon * master driver struct_master_controller_ops->recycle_ibi() method.
25773a379bbcSBoris Brezillon */
i3c_generic_ibi_recycle_slot(struct i3c_generic_ibi_pool * pool,struct i3c_ibi_slot * s)25783a379bbcSBoris Brezillon void i3c_generic_ibi_recycle_slot(struct i3c_generic_ibi_pool *pool,
25793a379bbcSBoris Brezillon struct i3c_ibi_slot *s)
25803a379bbcSBoris Brezillon {
25813a379bbcSBoris Brezillon struct i3c_generic_ibi_slot *slot;
25823a379bbcSBoris Brezillon unsigned long flags;
25833a379bbcSBoris Brezillon
25843a379bbcSBoris Brezillon if (!s)
25853a379bbcSBoris Brezillon return;
25863a379bbcSBoris Brezillon
25873a379bbcSBoris Brezillon slot = container_of(s, struct i3c_generic_ibi_slot, base);
25883a379bbcSBoris Brezillon spin_lock_irqsave(&pool->lock, flags);
25893a379bbcSBoris Brezillon list_add_tail(&slot->node, &pool->free_slots);
25903a379bbcSBoris Brezillon spin_unlock_irqrestore(&pool->lock, flags);
25913a379bbcSBoris Brezillon }
25923a379bbcSBoris Brezillon EXPORT_SYMBOL_GPL(i3c_generic_ibi_recycle_slot);
25933a379bbcSBoris Brezillon
i3c_master_check_ops(const struct i3c_master_controller_ops * ops)25943a379bbcSBoris Brezillon static int i3c_master_check_ops(const struct i3c_master_controller_ops *ops)
25953a379bbcSBoris Brezillon {
25963a379bbcSBoris Brezillon if (!ops || !ops->bus_init || !ops->priv_xfers ||
259788c50322SPrzemyslaw Gaj !ops->send_ccc_cmd || !ops->do_daa || !ops->i2c_xfers)
25983a379bbcSBoris Brezillon return -EINVAL;
25993a379bbcSBoris Brezillon
26003a379bbcSBoris Brezillon if (ops->request_ibi &&
26013a379bbcSBoris Brezillon (!ops->enable_ibi || !ops->disable_ibi || !ops->free_ibi ||
26023a379bbcSBoris Brezillon !ops->recycle_ibi_slot))
26033a379bbcSBoris Brezillon return -EINVAL;
26043a379bbcSBoris Brezillon
26053a379bbcSBoris Brezillon return 0;
26063a379bbcSBoris Brezillon }
26073a379bbcSBoris Brezillon
26083a379bbcSBoris Brezillon /**
26093a379bbcSBoris Brezillon * i3c_master_register() - register an I3C master
26103a379bbcSBoris Brezillon * @master: master used to send frames on the bus
26113a379bbcSBoris Brezillon * @parent: the parent device (the one that provides this I3C master
26123a379bbcSBoris Brezillon * controller)
26133a379bbcSBoris Brezillon * @ops: the master controller operations
26143a379bbcSBoris Brezillon * @secondary: true if you are registering a secondary master. Will return
26153a379bbcSBoris Brezillon * -ENOTSUPP if set to true since secondary masters are not yet
26163a379bbcSBoris Brezillon * supported
26173a379bbcSBoris Brezillon *
26183a379bbcSBoris Brezillon * This function takes care of everything for you:
26193a379bbcSBoris Brezillon *
26203a379bbcSBoris Brezillon * - creates and initializes the I3C bus
26213a379bbcSBoris Brezillon * - populates the bus with static I2C devs if @parent->of_node is not
26223a379bbcSBoris Brezillon * NULL
26233a379bbcSBoris Brezillon * - registers all I3C devices added by the controller during bus
26243a379bbcSBoris Brezillon * initialization
26253a379bbcSBoris Brezillon * - registers the I2C adapter and all I2C devices
26263a379bbcSBoris Brezillon *
26273a379bbcSBoris Brezillon * Return: 0 in case of success, a negative error code otherwise.
26283a379bbcSBoris Brezillon */
i3c_master_register(struct i3c_master_controller * master,struct device * parent,const struct i3c_master_controller_ops * ops,bool secondary)26293a379bbcSBoris Brezillon int i3c_master_register(struct i3c_master_controller *master,
26303a379bbcSBoris Brezillon struct device *parent,
26313a379bbcSBoris Brezillon const struct i3c_master_controller_ops *ops,
26323a379bbcSBoris Brezillon bool secondary)
26333a379bbcSBoris Brezillon {
2634ecc8fb54SVitor Soares unsigned long i2c_scl_rate = I3C_BUS_I2C_FM_PLUS_SCL_RATE;
26353a379bbcSBoris Brezillon struct i3c_bus *i3cbus = i3c_master_get_bus(master);
26363a379bbcSBoris Brezillon enum i3c_bus_mode mode = I3C_BUS_MODE_PURE;
26373a379bbcSBoris Brezillon struct i2c_dev_boardinfo *i2cbi;
26383a379bbcSBoris Brezillon int ret;
26393a379bbcSBoris Brezillon
26403a379bbcSBoris Brezillon /* We do not support secondary masters yet. */
26413a379bbcSBoris Brezillon if (secondary)
26423a379bbcSBoris Brezillon return -ENOTSUPP;
26433a379bbcSBoris Brezillon
26443a379bbcSBoris Brezillon ret = i3c_master_check_ops(ops);
26453a379bbcSBoris Brezillon if (ret)
26463a379bbcSBoris Brezillon return ret;
26473a379bbcSBoris Brezillon
26483a379bbcSBoris Brezillon master->dev.parent = parent;
26493a379bbcSBoris Brezillon master->dev.of_node = of_node_get(parent->of_node);
26503a379bbcSBoris Brezillon master->dev.bus = &i3c_bus_type;
26513a379bbcSBoris Brezillon master->dev.type = &i3c_masterdev_type;
26523a379bbcSBoris Brezillon master->dev.release = i3c_masterdev_release;
26533a379bbcSBoris Brezillon master->ops = ops;
26543a379bbcSBoris Brezillon master->secondary = secondary;
26553a379bbcSBoris Brezillon INIT_LIST_HEAD(&master->boardinfo.i2c);
26563a379bbcSBoris Brezillon INIT_LIST_HEAD(&master->boardinfo.i3c);
26573a379bbcSBoris Brezillon
26587dc2e0a8SJeremy Kerr ret = i3c_bus_init(i3cbus, master->dev.of_node);
26593a379bbcSBoris Brezillon if (ret)
26603a379bbcSBoris Brezillon return ret;
26613a379bbcSBoris Brezillon
26623a379bbcSBoris Brezillon device_initialize(&master->dev);
26633a379bbcSBoris Brezillon dev_set_name(&master->dev, "i3c-%d", i3cbus->id);
26643a379bbcSBoris Brezillon
26653a379bbcSBoris Brezillon ret = of_populate_i3c_bus(master);
26663a379bbcSBoris Brezillon if (ret)
26673a379bbcSBoris Brezillon goto err_put_dev;
26683a379bbcSBoris Brezillon
26693a379bbcSBoris Brezillon list_for_each_entry(i2cbi, &master->boardinfo.i2c, node) {
26703a379bbcSBoris Brezillon switch (i2cbi->lvr & I3C_LVR_I2C_INDEX_MASK) {
26713a379bbcSBoris Brezillon case I3C_LVR_I2C_INDEX(0):
26723a379bbcSBoris Brezillon if (mode < I3C_BUS_MODE_MIXED_FAST)
26733a379bbcSBoris Brezillon mode = I3C_BUS_MODE_MIXED_FAST;
26743a379bbcSBoris Brezillon break;
26753a379bbcSBoris Brezillon case I3C_LVR_I2C_INDEX(1):
2676cbf4f732SVitor Soares if (mode < I3C_BUS_MODE_MIXED_LIMITED)
2677cbf4f732SVitor Soares mode = I3C_BUS_MODE_MIXED_LIMITED;
2678cbf4f732SVitor Soares break;
26793a379bbcSBoris Brezillon case I3C_LVR_I2C_INDEX(2):
26803a379bbcSBoris Brezillon if (mode < I3C_BUS_MODE_MIXED_SLOW)
26813a379bbcSBoris Brezillon mode = I3C_BUS_MODE_MIXED_SLOW;
26823a379bbcSBoris Brezillon break;
26833a379bbcSBoris Brezillon default:
26843a379bbcSBoris Brezillon ret = -EINVAL;
26853a379bbcSBoris Brezillon goto err_put_dev;
26863a379bbcSBoris Brezillon }
2687ecc8fb54SVitor Soares
2688ecc8fb54SVitor Soares if (i2cbi->lvr & I3C_LVR_I2C_FM_MODE)
2689ecc8fb54SVitor Soares i2c_scl_rate = I3C_BUS_I2C_FM_SCL_RATE;
26903a379bbcSBoris Brezillon }
26913a379bbcSBoris Brezillon
2692ecc8fb54SVitor Soares ret = i3c_bus_set_mode(i3cbus, mode, i2c_scl_rate);
26933a379bbcSBoris Brezillon if (ret)
26943a379bbcSBoris Brezillon goto err_put_dev;
26953a379bbcSBoris Brezillon
26963a379bbcSBoris Brezillon master->wq = alloc_workqueue("%s", 0, 0, dev_name(parent));
26973a379bbcSBoris Brezillon if (!master->wq) {
26983a379bbcSBoris Brezillon ret = -ENOMEM;
26993a379bbcSBoris Brezillon goto err_put_dev;
27003a379bbcSBoris Brezillon }
27013a379bbcSBoris Brezillon
27023a379bbcSBoris Brezillon ret = i3c_master_bus_init(master);
27033a379bbcSBoris Brezillon if (ret)
27040d95f41eSJae Hyun Yoo goto err_put_dev;
27053a379bbcSBoris Brezillon
27063a379bbcSBoris Brezillon ret = device_add(&master->dev);
27073a379bbcSBoris Brezillon if (ret)
27083a379bbcSBoris Brezillon goto err_cleanup_bus;
27093a379bbcSBoris Brezillon
27103a379bbcSBoris Brezillon /*
27113a379bbcSBoris Brezillon * Expose our I3C bus as an I2C adapter so that I2C devices are exposed
27123a379bbcSBoris Brezillon * through the I2C subsystem.
27133a379bbcSBoris Brezillon */
27143a379bbcSBoris Brezillon ret = i3c_master_i2c_adapter_init(master);
27153a379bbcSBoris Brezillon if (ret)
27163a379bbcSBoris Brezillon goto err_del_dev;
27173a379bbcSBoris Brezillon
27184edeb9faSJeremy Kerr i3c_bus_notify(i3cbus, I3C_NOTIFY_BUS_ADD);
27194edeb9faSJeremy Kerr
27203a379bbcSBoris Brezillon /*
27213a379bbcSBoris Brezillon * We're done initializing the bus and the controller, we can now
2722708bc6ecSGeert Uytterhoeven * register I3C devices discovered during the initial DAA.
27233a379bbcSBoris Brezillon */
27243a379bbcSBoris Brezillon master->init_done = true;
27253a379bbcSBoris Brezillon i3c_bus_normaluse_lock(&master->bus);
27263a379bbcSBoris Brezillon i3c_master_register_new_i3c_devs(master);
27273a379bbcSBoris Brezillon i3c_bus_normaluse_unlock(&master->bus);
27283a379bbcSBoris Brezillon
27293a379bbcSBoris Brezillon return 0;
27303a379bbcSBoris Brezillon
27313a379bbcSBoris Brezillon err_del_dev:
27323a379bbcSBoris Brezillon device_del(&master->dev);
27333a379bbcSBoris Brezillon
27343a379bbcSBoris Brezillon err_cleanup_bus:
27353a379bbcSBoris Brezillon i3c_master_bus_cleanup(master);
27363a379bbcSBoris Brezillon
27373a379bbcSBoris Brezillon err_put_dev:
27383a379bbcSBoris Brezillon put_device(&master->dev);
27393a379bbcSBoris Brezillon
27403a379bbcSBoris Brezillon return ret;
27413a379bbcSBoris Brezillon }
27423a379bbcSBoris Brezillon EXPORT_SYMBOL_GPL(i3c_master_register);
27433a379bbcSBoris Brezillon
27443a379bbcSBoris Brezillon /**
27453a379bbcSBoris Brezillon * i3c_master_unregister() - unregister an I3C master
27463a379bbcSBoris Brezillon * @master: master used to send frames on the bus
27473a379bbcSBoris Brezillon *
27483a379bbcSBoris Brezillon * Basically undo everything done in i3c_master_register().
27493a379bbcSBoris Brezillon */
i3c_master_unregister(struct i3c_master_controller * master)27500f74f8b6SUwe Kleine-König void i3c_master_unregister(struct i3c_master_controller *master)
27513a379bbcSBoris Brezillon {
27524edeb9faSJeremy Kerr i3c_bus_notify(&master->bus, I3C_NOTIFY_BUS_REMOVE);
27534edeb9faSJeremy Kerr
27543a379bbcSBoris Brezillon i3c_master_i2c_adapter_cleanup(master);
27553a379bbcSBoris Brezillon i3c_master_unregister_i3c_devs(master);
27563a379bbcSBoris Brezillon i3c_master_bus_cleanup(master);
27573a379bbcSBoris Brezillon device_unregister(&master->dev);
27583a379bbcSBoris Brezillon }
27593a379bbcSBoris Brezillon EXPORT_SYMBOL_GPL(i3c_master_unregister);
27603a379bbcSBoris Brezillon
i3c_dev_setdasa_locked(struct i3c_dev_desc * dev)2761672825cdSJack Chen int i3c_dev_setdasa_locked(struct i3c_dev_desc *dev)
2762672825cdSJack Chen {
2763672825cdSJack Chen struct i3c_master_controller *master;
2764672825cdSJack Chen
2765672825cdSJack Chen if (!dev)
2766672825cdSJack Chen return -ENOENT;
2767672825cdSJack Chen
2768672825cdSJack Chen master = i3c_dev_get_master(dev);
2769672825cdSJack Chen if (!master)
2770672825cdSJack Chen return -EINVAL;
2771672825cdSJack Chen
2772672825cdSJack Chen if (!dev->boardinfo || !dev->boardinfo->init_dyn_addr ||
2773672825cdSJack Chen !dev->boardinfo->static_addr)
2774672825cdSJack Chen return -EINVAL;
2775672825cdSJack Chen
2776672825cdSJack Chen return i3c_master_setdasa_locked(master, dev->info.static_addr,
2777672825cdSJack Chen dev->boardinfo->init_dyn_addr);
2778672825cdSJack Chen }
2779672825cdSJack Chen
i3c_dev_do_priv_xfers_locked(struct i3c_dev_desc * dev,struct i3c_priv_xfer * xfers,int nxfers)27803a379bbcSBoris Brezillon int i3c_dev_do_priv_xfers_locked(struct i3c_dev_desc *dev,
27813a379bbcSBoris Brezillon struct i3c_priv_xfer *xfers,
27823a379bbcSBoris Brezillon int nxfers)
27833a379bbcSBoris Brezillon {
27843a379bbcSBoris Brezillon struct i3c_master_controller *master;
27853a379bbcSBoris Brezillon
27863a379bbcSBoris Brezillon if (!dev)
27873a379bbcSBoris Brezillon return -ENOENT;
27883a379bbcSBoris Brezillon
27893a379bbcSBoris Brezillon master = i3c_dev_get_master(dev);
27903a379bbcSBoris Brezillon if (!master || !xfers)
27913a379bbcSBoris Brezillon return -EINVAL;
27923a379bbcSBoris Brezillon
27933a379bbcSBoris Brezillon if (!master->ops->priv_xfers)
27943a379bbcSBoris Brezillon return -ENOTSUPP;
27953a379bbcSBoris Brezillon
27963a379bbcSBoris Brezillon return master->ops->priv_xfers(dev, xfers, nxfers);
27973a379bbcSBoris Brezillon }
27983a379bbcSBoris Brezillon
i3c_dev_disable_ibi_locked(struct i3c_dev_desc * dev)27993a379bbcSBoris Brezillon int i3c_dev_disable_ibi_locked(struct i3c_dev_desc *dev)
28003a379bbcSBoris Brezillon {
28013a379bbcSBoris Brezillon struct i3c_master_controller *master;
28023a379bbcSBoris Brezillon int ret;
28033a379bbcSBoris Brezillon
28043a379bbcSBoris Brezillon if (!dev->ibi)
28053a379bbcSBoris Brezillon return -EINVAL;
28063a379bbcSBoris Brezillon
28073a379bbcSBoris Brezillon master = i3c_dev_get_master(dev);
28083a379bbcSBoris Brezillon ret = master->ops->disable_ibi(dev);
28093a379bbcSBoris Brezillon if (ret)
28103a379bbcSBoris Brezillon return ret;
28113a379bbcSBoris Brezillon
28123a379bbcSBoris Brezillon reinit_completion(&dev->ibi->all_ibis_handled);
28133a379bbcSBoris Brezillon if (atomic_read(&dev->ibi->pending_ibis))
28143a379bbcSBoris Brezillon wait_for_completion(&dev->ibi->all_ibis_handled);
28153a379bbcSBoris Brezillon
28163a379bbcSBoris Brezillon dev->ibi->enabled = false;
28173a379bbcSBoris Brezillon
28183a379bbcSBoris Brezillon return 0;
28193a379bbcSBoris Brezillon }
28203a379bbcSBoris Brezillon
i3c_dev_enable_ibi_locked(struct i3c_dev_desc * dev)28213a379bbcSBoris Brezillon int i3c_dev_enable_ibi_locked(struct i3c_dev_desc *dev)
28223a379bbcSBoris Brezillon {
28233a379bbcSBoris Brezillon struct i3c_master_controller *master = i3c_dev_get_master(dev);
28243a379bbcSBoris Brezillon int ret;
28253a379bbcSBoris Brezillon
28263a379bbcSBoris Brezillon if (!dev->ibi)
28273a379bbcSBoris Brezillon return -EINVAL;
28283a379bbcSBoris Brezillon
28293a379bbcSBoris Brezillon ret = master->ops->enable_ibi(dev);
28303a379bbcSBoris Brezillon if (!ret)
28313a379bbcSBoris Brezillon dev->ibi->enabled = true;
28323a379bbcSBoris Brezillon
28333a379bbcSBoris Brezillon return ret;
28343a379bbcSBoris Brezillon }
28353a379bbcSBoris Brezillon
i3c_dev_request_ibi_locked(struct i3c_dev_desc * dev,const struct i3c_ibi_setup * req)28363a379bbcSBoris Brezillon int i3c_dev_request_ibi_locked(struct i3c_dev_desc *dev,
28373a379bbcSBoris Brezillon const struct i3c_ibi_setup *req)
28383a379bbcSBoris Brezillon {
28393a379bbcSBoris Brezillon struct i3c_master_controller *master = i3c_dev_get_master(dev);
28403a379bbcSBoris Brezillon struct i3c_device_ibi_info *ibi;
28413a379bbcSBoris Brezillon int ret;
28423a379bbcSBoris Brezillon
28433a379bbcSBoris Brezillon if (!master->ops->request_ibi)
28443a379bbcSBoris Brezillon return -ENOTSUPP;
28453a379bbcSBoris Brezillon
28463a379bbcSBoris Brezillon if (dev->ibi)
28473a379bbcSBoris Brezillon return -EBUSY;
28483a379bbcSBoris Brezillon
28493a379bbcSBoris Brezillon ibi = kzalloc(sizeof(*ibi), GFP_KERNEL);
28503a379bbcSBoris Brezillon if (!ibi)
28513a379bbcSBoris Brezillon return -ENOMEM;
28523a379bbcSBoris Brezillon
28533a379bbcSBoris Brezillon atomic_set(&ibi->pending_ibis, 0);
28543a379bbcSBoris Brezillon init_completion(&ibi->all_ibis_handled);
28553a379bbcSBoris Brezillon ibi->handler = req->handler;
28563a379bbcSBoris Brezillon ibi->max_payload_len = req->max_payload_len;
28573a379bbcSBoris Brezillon ibi->num_slots = req->num_slots;
28583a379bbcSBoris Brezillon
28593a379bbcSBoris Brezillon dev->ibi = ibi;
28603a379bbcSBoris Brezillon ret = master->ops->request_ibi(dev, req);
28613a379bbcSBoris Brezillon if (ret) {
28623a379bbcSBoris Brezillon kfree(ibi);
28633a379bbcSBoris Brezillon dev->ibi = NULL;
28643a379bbcSBoris Brezillon }
28653a379bbcSBoris Brezillon
28663a379bbcSBoris Brezillon return ret;
28673a379bbcSBoris Brezillon }
28683a379bbcSBoris Brezillon
i3c_dev_free_ibi_locked(struct i3c_dev_desc * dev)28693a379bbcSBoris Brezillon void i3c_dev_free_ibi_locked(struct i3c_dev_desc *dev)
28703a379bbcSBoris Brezillon {
28713a379bbcSBoris Brezillon struct i3c_master_controller *master = i3c_dev_get_master(dev);
28723a379bbcSBoris Brezillon
28733a379bbcSBoris Brezillon if (!dev->ibi)
28743a379bbcSBoris Brezillon return;
28753a379bbcSBoris Brezillon
28763a379bbcSBoris Brezillon if (WARN_ON(dev->ibi->enabled))
28773a379bbcSBoris Brezillon WARN_ON(i3c_dev_disable_ibi_locked(dev));
28783a379bbcSBoris Brezillon
28793a379bbcSBoris Brezillon master->ops->free_ibi(dev);
28803a379bbcSBoris Brezillon kfree(dev->ibi);
28813a379bbcSBoris Brezillon dev->ibi = NULL;
28823a379bbcSBoris Brezillon }
28833a379bbcSBoris Brezillon
i3c_init(void)28843a379bbcSBoris Brezillon static int __init i3c_init(void)
28853a379bbcSBoris Brezillon {
28867dc2e0a8SJeremy Kerr int res;
288772a4501bSJamie Iles
28887dc2e0a8SJeremy Kerr res = of_alias_get_highest_id("i3c");
28897dc2e0a8SJeremy Kerr if (res >= 0) {
28907dc2e0a8SJeremy Kerr mutex_lock(&i3c_core_lock);
28917dc2e0a8SJeremy Kerr __i3c_first_dynamic_bus_num = res + 1;
28927dc2e0a8SJeremy Kerr mutex_unlock(&i3c_core_lock);
28937dc2e0a8SJeremy Kerr }
28947dc2e0a8SJeremy Kerr
28957dc2e0a8SJeremy Kerr res = bus_register_notifier(&i2c_bus_type, &i2cdev_notifier);
289672a4501bSJamie Iles if (res)
289772a4501bSJamie Iles return res;
289872a4501bSJamie Iles
289972a4501bSJamie Iles res = bus_register(&i3c_bus_type);
290072a4501bSJamie Iles if (res)
290172a4501bSJamie Iles goto out_unreg_notifier;
290272a4501bSJamie Iles
290372a4501bSJamie Iles return 0;
290472a4501bSJamie Iles
290572a4501bSJamie Iles out_unreg_notifier:
290672a4501bSJamie Iles bus_unregister_notifier(&i2c_bus_type, &i2cdev_notifier);
290772a4501bSJamie Iles
290872a4501bSJamie Iles return res;
29093a379bbcSBoris Brezillon }
29103a379bbcSBoris Brezillon subsys_initcall(i3c_init);
29113a379bbcSBoris Brezillon
i3c_exit(void)29123a379bbcSBoris Brezillon static void __exit i3c_exit(void)
29133a379bbcSBoris Brezillon {
291472a4501bSJamie Iles bus_unregister_notifier(&i2c_bus_type, &i2cdev_notifier);
29153a379bbcSBoris Brezillon idr_destroy(&i3c_bus_idr);
29163a379bbcSBoris Brezillon bus_unregister(&i3c_bus_type);
29173a379bbcSBoris Brezillon }
29183a379bbcSBoris Brezillon module_exit(i3c_exit);
29193a379bbcSBoris Brezillon
29203a379bbcSBoris Brezillon MODULE_AUTHOR("Boris Brezillon <boris.brezillon@bootlin.com>");
29213a379bbcSBoris Brezillon MODULE_DESCRIPTION("I3C core");
29223a379bbcSBoris Brezillon MODULE_LICENSE("GPL v2");
2923