summaryrefslogtreecommitdiff
path: root/drivers/i3c
diff options
context:
space:
mode:
authorOleksandr Shulzhenko <oleksandr.shulzhenko.viktorovych@intel.com>2022-01-27 13:24:40 +0300
committeroshulzhenko <96782923+oshulzhenko@users.noreply.github.com>2022-02-07 17:14:34 +0300
commit36e4e3fa141e0975347104573a024f1160377808 (patch)
tree0960f9a8f42218e67d2b154ef3a1da42c9d34c77 /drivers/i3c
parentb7504577edef85b5a7b2120d7ce81c8a933163f3 (diff)
downloadlinux-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.c24
-rw-r--r--drivers/i3c/internals.h1
-rw-r--r--drivers/i3c/master.c26
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);