diff options
author | Oleksandr Shulzhenko <oleksandr.shulzhenko.viktorovych@intel.com> | 2022-01-27 13:24:40 +0300 |
---|---|---|
committer | oshulzhenko <96782923+oshulzhenko@users.noreply.github.com> | 2022-02-07 17:14:34 +0300 |
commit | 36e4e3fa141e0975347104573a024f1160377808 (patch) | |
tree | 0960f9a8f42218e67d2b154ef3a1da42c9d34c77 /drivers/i3c | |
parent | b7504577edef85b5a7b2120d7ce81c8a933163f3 (diff) | |
download | linux-36e4e3fa141e0975347104573a024f1160377808.tar.xz |
i3c: master: Implement CCC GETSTATUS function
Get Device Status (GETSTATUS) is a Direct CCC that is sent by
I3C controller to I3C Target device to read I3C Target status.
Signed-off-by: Oleksandr Shulzhenko <oleksandr.shulzhenko.viktorovych@intel.com>
Diffstat (limited to 'drivers/i3c')
-rw-r--r-- | drivers/i3c/device.c | 24 | ||||
-rw-r--r-- | drivers/i3c/internals.h | 1 | ||||
-rw-r--r-- | drivers/i3c/master.c | 26 |
3 files changed, 51 insertions, 0 deletions
diff --git a/drivers/i3c/device.c b/drivers/i3c/device.c index e92d3e9a52bd..671b63a19591 100644 --- a/drivers/i3c/device.c +++ b/drivers/i3c/device.c @@ -283,3 +283,27 @@ void i3c_driver_unregister(struct i3c_driver *drv) driver_unregister(&drv->driver); } EXPORT_SYMBOL_GPL(i3c_driver_unregister); + +/** + * i3c_device_getstatus_ccc() - receive device status + * + * @dev: I3C device to get the status for + * @info: I3C device info to fill the status in + * + * Receive I3C device status from I3C master device via corresponding CCC + * command + * + * Return: 0 in case of success, a negative error code otherwise. + */ +int i3c_device_getstatus_ccc(struct i3c_device *dev, struct i3c_device_info *info) +{ + int ret = -EINVAL; + + i3c_bus_normaluse_lock(dev->bus); + if (dev->desc) + ret = i3c_dev_getstatus_locked(dev->desc, info); + i3c_bus_normaluse_unlock(dev->bus); + + return ret; +} +EXPORT_SYMBOL_GPL(i3c_device_getstatus_ccc); diff --git a/drivers/i3c/internals.h b/drivers/i3c/internals.h index a6deedf5ce06..d633df3bfcf9 100644 --- a/drivers/i3c/internals.h +++ b/drivers/i3c/internals.h @@ -24,5 +24,6 @@ int i3c_dev_enable_ibi_locked(struct i3c_dev_desc *dev); int i3c_dev_request_ibi_locked(struct i3c_dev_desc *dev, const struct i3c_ibi_setup *req); void i3c_dev_free_ibi_locked(struct i3c_dev_desc *dev); +int i3c_dev_getstatus_locked(struct i3c_dev_desc *dev, struct i3c_device_info *info); int i3c_for_each_dev(void *data, int (*fn)(struct device *, void *)); #endif /* I3C_INTERNAL_H */ diff --git a/drivers/i3c/master.c b/drivers/i3c/master.c index c6b60be02562..81ce385a38ac 100644 --- a/drivers/i3c/master.c +++ b/drivers/i3c/master.c @@ -1256,6 +1256,32 @@ out: return ret; } +int i3c_dev_getstatus_locked(struct i3c_dev_desc *dev, + struct i3c_device_info *info) +{ + struct i3c_master_controller *master = i3c_dev_get_master(dev); + struct i3c_ccc_getstatus *getsts; + struct i3c_ccc_cmd_dest dest; + struct i3c_ccc_cmd cmd; + int ret; + + getsts = i3c_ccc_cmd_dest_init(&dest, info->dyn_addr, sizeof(*getsts)); + if (!getsts) + return -ENOMEM; + + i3c_ccc_cmd_init(&cmd, true, I3C_CCC_GETSTATUS, &dest, 1); + ret = i3c_master_send_ccc_cmd_locked(master, &cmd); + if (ret) + goto out; + + info->status = getsts->status; + +out: + i3c_ccc_cmd_dest_cleanup(&dest); + + return ret; +} + static int i3c_master_retrieve_dev_info(struct i3c_dev_desc *dev) { struct i3c_master_controller *master = i3c_dev_get_master(dev); |