2024-01-10 17:53:08

by Frank Li

[permalink] [raw]
Subject: [PATCH v2 0/7] I3C target mode support

This patch introduces support for I3C target mode, which is referenced
with a PCIe Endpoint system. It also establishes a configuration framework
(configfs) for the I3C target controller driver and the I3C target function
driver

Typic usage as

The user can configure the i3c-target-tty device using configfs entry. In
order to change the vendorid, the following commands can be used

# echo 0x011b > functions/tty/func1/vendor_id
# echo 0x1000 > functions/tty/func1/part_id
# echo 0x6 > functions/tty/t/bcr

Binding i3c-target-tty Device to target Controller
------------------------------------------------

In order for the target function device to be useful, it has to be bound to
a I3C target controller driver. Use the configfs to bind the function
device to one of the controller driver present in the system::

# ln -s functions/pci_epf_test/func1 controllers/44330000.i3c-target/

Host side:
cat /dev/ttyI3C0
Taret side:
echo abc >/dev/ttyI3C0

Change from v1 to v2
- change "slave" to "target"
- include master side tty patch
- fixed dtbcheck problem
- fixed kerne-doc check warning

Some review comment may be lost since it is quite long time since v1. Now
master side dependent patches already in linux-next. So sent target side
patches with tty support again.

No sure why an additional "\r\n" appended.

Frank Li (7):
i3c: add target mode support
dt-bindings: i3c: svc: add compatible string i3c:
silvaco,i3c-target-v1
Documentation: i3c: Add I3C target mode controller and function
i3c: target: add svc target controller support
i3c: target: func: add tty driver
i3c: add API i3c_dev_gettstatus_format1() to get target device status
tty: i3c: add TTY over I3C master support

.../bindings/i3c/silvaco,i3c-master.yaml | 7 +-
Documentation/driver-api/i3c/index.rst | 1 +
.../driver-api/i3c/target/i3c-target-cfs.rst | 109 +++
.../driver-api/i3c/target/i3c-target.rst | 189 +++++
.../driver-api/i3c/target/i3c-tty-howto.rst | 109 +++
Documentation/driver-api/i3c/target/index.rst | 13 +
drivers/i3c/Kconfig | 32 +-
drivers/i3c/Makefile | 4 +
drivers/i3c/device.c | 24 +
drivers/i3c/func/Kconfig | 9 +
drivers/i3c/func/Makefile | 3 +
drivers/i3c/func/tty.c | 475 +++++++++++
drivers/i3c/i3c-cfs.c | 389 +++++++++
drivers/i3c/internals.h | 1 +
drivers/i3c/master.c | 26 +
drivers/i3c/target.c | 453 ++++++++++
drivers/i3c/target/Kconfig | 9 +
drivers/i3c/target/Makefile | 4 +
drivers/i3c/target/svc-i3c-target.c | 795 ++++++++++++++++++
drivers/tty/Kconfig | 13 +
drivers/tty/Makefile | 1 +
drivers/tty/i3c_tty.c | 426 ++++++++++
include/linux/i3c/device.h | 1 +
include/linux/i3c/target.h | 511 +++++++++++
24 files changed, 3600 insertions(+), 4 deletions(-)
create mode 100644 Documentation/driver-api/i3c/target/i3c-target-cfs.rst
create mode 100644 Documentation/driver-api/i3c/target/i3c-target.rst
create mode 100644 Documentation/driver-api/i3c/target/i3c-tty-howto.rst
create mode 100644 Documentation/driver-api/i3c/target/index.rst
create mode 100644 drivers/i3c/func/Kconfig
create mode 100644 drivers/i3c/func/Makefile
create mode 100644 drivers/i3c/func/tty.c
create mode 100644 drivers/i3c/i3c-cfs.c
create mode 100644 drivers/i3c/target.c
create mode 100644 drivers/i3c/target/Kconfig
create mode 100644 drivers/i3c/target/Makefile
create mode 100644 drivers/i3c/target/svc-i3c-target.c
create mode 100644 drivers/tty/i3c_tty.c
create mode 100644 include/linux/i3c/target.h

--
2.34.1



2024-01-10 17:53:31

by Frank Li

[permalink] [raw]
Subject: [PATCH v2 2/7] dt-bindings: i3c: svc: add compatible string i3c: silvaco,i3c-target-v1

Add compatible string 'silvaco,i3c-target-v1' for target mode.

Signed-off-by: Frank Li <[email protected]>
---
.../devicetree/bindings/i3c/silvaco,i3c-master.yaml | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/Documentation/devicetree/bindings/i3c/silvaco,i3c-master.yaml b/Documentation/devicetree/bindings/i3c/silvaco,i3c-master.yaml
index 133855f11b4f5..17849c91d4d2b 100644
--- a/Documentation/devicetree/bindings/i3c/silvaco,i3c-master.yaml
+++ b/Documentation/devicetree/bindings/i3c/silvaco,i3c-master.yaml
@@ -4,7 +4,7 @@
$id: http://devicetree.org/schemas/i3c/silvaco,i3c-master.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#

-title: Silvaco I3C master
+title: Silvaco I3C master/target

maintainers:
- Conor Culhane <[email protected]>
@@ -14,8 +14,9 @@ allOf:

properties:
compatible:
- const: silvaco,i3c-master-v1
-
+ enum:
+ - silvaco,i3c-master-v1
+ - silvaco,i3c-target-v1
reg:
maxItems: 1

--
2.34.1


2024-01-10 17:53:33

by Frank Li

[permalink] [raw]
Subject: [PATCH v2 1/7] i3c: add target mode support

Introduce a new target core layer in order to support target functions in
linux kernel. This comprises the controller library and function library.
Controller library implements functions specific to an target controller
and function library implements functions specific to an target function.

Introduce a new configfs entry to configure the target function configuring
and bind the target function with target controller.

Signed-off-by: Frank Li <[email protected]>
---
drivers/i3c/Kconfig | 28 +-
drivers/i3c/Makefile | 2 +
drivers/i3c/i3c-cfs.c | 389 ++++++++++++++++++++++++++++
drivers/i3c/target.c | 453 ++++++++++++++++++++++++++++++++
include/linux/i3c/target.h | 511 +++++++++++++++++++++++++++++++++++++
5 files changed, 1382 insertions(+), 1 deletion(-)
create mode 100644 drivers/i3c/i3c-cfs.c
create mode 100644 drivers/i3c/target.c
create mode 100644 include/linux/i3c/target.h

diff --git a/drivers/i3c/Kconfig b/drivers/i3c/Kconfig
index 30a441506f61c..d59a7eb83d13a 100644
--- a/drivers/i3c/Kconfig
+++ b/drivers/i3c/Kconfig
@@ -10,7 +10,7 @@ menuconfig I3C
support for high speed transfers and native interrupt support
without the need for extra pins.

- The I3C protocol also standardizes the slave device types and is
+ The I3C protocol also standardizes the target device types and is
mainly designed to communicate with sensors.

If you want I3C support, you should say Y here and also to the
@@ -22,3 +22,29 @@ menuconfig I3C
if I3C
source "drivers/i3c/master/Kconfig"
endif # I3C
+
+config I3C_TARGET
+ bool "I3C Target Support"
+ help
+ Support I3C Target Mode.
+
+ Enable this configuration option to support configurable I3C target.
+ This should be enabled if the platform has a I3C controller that can
+ operate in target mode.
+
+ Enabling this option will build the I3C target library, which includes
+ target controller library and target function library.
+
+ If in doubt, say "N" to disable target support.
+
+config I3C_TARGET_CONFIGFS
+ bool "I3C Target Configfs Support"
+ depends on I3C_TARGET
+ select CONFIGFS_FS
+ help
+ Configfs entry for target function and controller.
+
+ This will enable the configfs entry that can be used to configure
+ the target function and used to bind the function with a target
+ controller.
+
diff --git a/drivers/i3c/Makefile b/drivers/i3c/Makefile
index 11982efbc6d91..475afb40429e0 100644
--- a/drivers/i3c/Makefile
+++ b/drivers/i3c/Makefile
@@ -2,3 +2,5 @@
i3c-y := device.o master.o
obj-$(CONFIG_I3C) += i3c.o
obj-$(CONFIG_I3C) += master/
+obj-$(CONFIG_I3C_TARGET) += target.o
+obj-$(CONFIG_I3C_TARGET_CONFIGFS) += i3c-cfs.o
diff --git a/drivers/i3c/i3c-cfs.c b/drivers/i3c/i3c-cfs.c
new file mode 100644
index 0000000000000..a2f0f44fcdaea
--- /dev/null
+++ b/drivers/i3c/i3c-cfs.c
@@ -0,0 +1,389 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Configfs to configure the I3C Slave
+ *
+ * Copyright (C) 2023 NXP
+ * Author: Frank Li <[email protected]>
+ */
+
+#include <linux/configfs.h>
+#include <linux/module.h>
+#include <linux/i3c/target.h>
+#include <linux/idr.h>
+#include <linux/slab.h>
+
+static DEFINE_MUTEX(functions_mutex);
+static struct config_group *functions_group;
+static struct config_group *controllers_group;
+
+struct i3c_target_func_group {
+ struct config_group group;
+ struct i3c_target_func *func;
+};
+
+struct i3c_target_ctrl_group {
+ struct config_group group;
+ struct i3c_target_ctrl *ctrl;
+};
+
+static inline struct i3c_target_func_group *to_i3c_target_func_group(struct config_item *item)
+{
+ return container_of(to_config_group(item), struct i3c_target_func_group, group);
+}
+
+static inline struct i3c_target_ctrl_group *to_i3c_target_ctrl_group(struct config_item *item)
+{
+ return container_of(to_config_group(item), struct i3c_target_ctrl_group, group);
+}
+
+static int i3c_target_ctrl_func_link(struct config_item *ctrl_cfg, struct config_item *func_cfg)
+{
+ struct i3c_target_func_group *func_group = to_i3c_target_func_group(func_cfg);
+ struct i3c_target_ctrl_group *ctrl_group = to_i3c_target_ctrl_group(ctrl_cfg);
+ struct i3c_target_ctrl *ctrl = ctrl_group->ctrl;
+ struct i3c_target_func *func = func_group->func;
+ int ret;
+
+ ret = i3c_target_ctrl_add_func(ctrl, func);
+ if (ret)
+ return ret;
+
+ ret = i3c_target_func_bind(func);
+ if (ret) {
+ i3c_target_ctrl_remove_func(ctrl, func);
+ return ret;
+ }
+
+ return 0;
+}
+
+static void i3c_target_ctrl_func_unlink(struct config_item *ctrl_cfg, struct config_item *func_cfg)
+{
+ struct i3c_target_func_group *func_group = to_i3c_target_func_group(func_cfg->ci_parent);
+ struct i3c_target_ctrl_group *ctrl_group = to_i3c_target_ctrl_group(ctrl_cfg);
+ struct i3c_target_ctrl *ctrl = ctrl_group->ctrl;
+ struct i3c_target_func *func = func_group->func;
+
+ i3c_target_func_unbind(func);
+ i3c_target_ctrl_remove_func(ctrl, func);
+}
+
+static ssize_t i3c_target_ctrl_hotjoin_store(struct config_item *item, const char *page, size_t len)
+{
+ struct i3c_target_ctrl_group *ctrl_group = to_i3c_target_ctrl_group(item);
+ struct i3c_target_ctrl *ctrl;
+ int ret;
+
+ ctrl = ctrl_group->ctrl;
+
+ ret = i3c_target_ctrl_hotjoin(ctrl);
+ if (ret) {
+ dev_err(&ctrl->dev, "failed to hotjoin i3c target controller\n");
+ return -EINVAL;
+ }
+
+ return len;
+}
+
+static ssize_t i3c_target_ctrl_hotjoin_show(struct config_item *item, char *page)
+{
+ return sysfs_emit(page, "%d\n", 0);
+}
+
+CONFIGFS_ATTR(i3c_target_ctrl_, hotjoin);
+
+static struct configfs_item_operations i3c_target_ctrl_item_ops = {
+ .allow_link = i3c_target_ctrl_func_link,
+ .drop_link = i3c_target_ctrl_func_unlink,
+};
+
+static struct configfs_attribute *i3c_target_ctrl_attrs[] = {
+ &i3c_target_ctrl_attr_hotjoin,
+ NULL,
+};
+
+static const struct config_item_type i3c_target_ctrl_type = {
+ .ct_item_ops = &i3c_target_ctrl_item_ops,
+ .ct_attrs = i3c_target_ctrl_attrs,
+ .ct_owner = THIS_MODULE,
+};
+
+/**
+ * i3c_target_cfs_add_ctrl_group() - add I3C target controller group
+ * @ctrl: I3C target controller device
+ *
+ * Return: Pointer to struct config_group
+ */
+struct config_group *i3c_target_cfs_add_ctrl_group(struct i3c_target_ctrl *ctrl)
+{
+ struct i3c_target_ctrl_group *ctrl_group;
+ struct config_group *group;
+ int ret;
+
+ ctrl_group = kzalloc(sizeof(*ctrl_group), GFP_KERNEL);
+ if (!ctrl_group) {
+ ret = -ENOMEM;
+ goto err;
+ }
+
+ group = &ctrl_group->group;
+
+ config_group_init_type_name(group, dev_name(&ctrl->dev), &i3c_target_ctrl_type);
+ ret = configfs_register_group(controllers_group, group);
+ if (ret) {
+ pr_err("failed to register configfs group for %s\n", dev_name(&ctrl->dev));
+ goto err_register_group;
+ }
+
+ ctrl_group->ctrl = ctrl;
+
+ return group;
+
+err_register_group:
+ kfree(ctrl_group);
+
+err:
+ return ERR_PTR(ret);
+}
+EXPORT_SYMBOL(i3c_target_cfs_add_ctrl_group);
+
+/**
+ * i3c_target_cfs_remove_ctrl_group() - remove I3C target controller group
+ * @group: the group to be removed
+ */
+void i3c_target_cfs_remove_ctrl_group(struct config_group *group)
+{
+ struct i3c_target_ctrl_group *ctrl_group;
+
+ if (!group)
+ return;
+
+ ctrl_group = container_of(group, struct i3c_target_ctrl_group, group);
+ i3c_target_ctrl_put(ctrl_group->ctrl);
+ configfs_unregister_group(&ctrl_group->group);
+ kfree(ctrl_group);
+}
+EXPORT_SYMBOL(i3c_target_cfs_remove_ctrl_group);
+
+#define I3C_SLAVE_ATTR_R(_name) \
+static ssize_t i3c_target_func_##_name##_show(struct config_item *item, char *page) \
+{ \
+ struct i3c_target_func *func = to_i3c_target_func_group(item)->func; \
+ return sysfs_emit(page, "0x%04x\n", func->_name); \
+}
+
+#define I3C_SLAVE_ATTR_W(_name, _u) \
+static ssize_t i3c_target_func_##_name##_store(struct config_item *item, \
+ const char *page, size_t len) \
+{ \
+ _u val; \
+ struct i3c_target_func *func = to_i3c_target_func_group(item)->func; \
+ if (kstrto##_u(page, 0, &val) < 0) \
+ return -EINVAL; \
+ func->_name = val; \
+ return len; \
+}
+
+I3C_SLAVE_ATTR_R(vendor_id);
+I3C_SLAVE_ATTR_W(vendor_id, u16);
+CONFIGFS_ATTR(i3c_target_func_, vendor_id);
+
+I3C_SLAVE_ATTR_R(vendor_info);
+I3C_SLAVE_ATTR_W(vendor_info, u16);
+CONFIGFS_ATTR(i3c_target_func_, vendor_info);
+
+I3C_SLAVE_ATTR_R(part_id);
+I3C_SLAVE_ATTR_W(part_id, u16);
+CONFIGFS_ATTR(i3c_target_func_, part_id);
+
+I3C_SLAVE_ATTR_R(instance_id);
+I3C_SLAVE_ATTR_W(instance_id, u8);
+CONFIGFS_ATTR(i3c_target_func_, instance_id);
+
+I3C_SLAVE_ATTR_R(ext_id);
+I3C_SLAVE_ATTR_W(ext_id, u16);
+CONFIGFS_ATTR(i3c_target_func_, ext_id);
+
+I3C_SLAVE_ATTR_R(max_write_len);
+I3C_SLAVE_ATTR_W(max_write_len, u16);
+CONFIGFS_ATTR(i3c_target_func_, max_write_len);
+
+I3C_SLAVE_ATTR_R(max_read_len);
+I3C_SLAVE_ATTR_W(max_read_len, u16);
+CONFIGFS_ATTR(i3c_target_func_, max_read_len);
+
+I3C_SLAVE_ATTR_R(bcr);
+I3C_SLAVE_ATTR_W(bcr, u8);
+CONFIGFS_ATTR(i3c_target_func_, bcr);
+
+I3C_SLAVE_ATTR_R(dcr);
+I3C_SLAVE_ATTR_W(dcr, u8);
+CONFIGFS_ATTR(i3c_target_func_, dcr);
+
+static struct configfs_attribute *i3c_target_func_attrs[] = {
+ &i3c_target_func_attr_vendor_id,
+ &i3c_target_func_attr_vendor_info,
+ &i3c_target_func_attr_part_id,
+ &i3c_target_func_attr_instance_id,
+ &i3c_target_func_attr_ext_id,
+ &i3c_target_func_attr_max_write_len,
+ &i3c_target_func_attr_max_read_len,
+ &i3c_target_func_attr_bcr,
+ &i3c_target_func_attr_dcr,
+ NULL,
+};
+
+static const struct config_item_type i3c_target_func_type = {
+ .ct_attrs = i3c_target_func_attrs,
+ .ct_owner = THIS_MODULE,
+};
+
+static struct config_group *i3c_target_func_make(struct config_group *group, const char *name)
+{
+ struct i3c_target_func_group *func_group;
+ struct i3c_target_func *func;
+ int err;
+
+ func_group = kzalloc(sizeof(*func_group), GFP_KERNEL);
+ if (!func_group)
+ return ERR_PTR(-ENOMEM);
+
+ config_group_init_type_name(&func_group->group, name, &i3c_target_func_type);
+
+ func = i3c_target_func_create(group->cg_item.ci_name, name);
+ if (IS_ERR(func)) {
+ pr_err("failed to create i3c target function device\n");
+ err = -EINVAL;
+ goto free_group;
+ }
+
+ func->group = &func_group->group;
+
+ func_group->func = func;
+
+ return &func_group->group;
+
+free_group:
+ kfree(func_group);
+
+ return ERR_PTR(err);
+}
+
+static void i3c_target_func_drop(struct config_group *group, struct config_item *item)
+{
+ config_item_put(item);
+}
+
+static struct configfs_group_operations i3c_target_func_group_ops = {
+ .make_group = &i3c_target_func_make,
+ .drop_item = &i3c_target_func_drop,
+};
+
+static const struct config_item_type i3c_target_func_group_type = {
+ .ct_group_ops = &i3c_target_func_group_ops,
+ .ct_owner = THIS_MODULE,
+};
+
+/**
+ * i3c_target_cfs_add_func_group() - add I3C target function group
+ * @name: group name
+ *
+ * Return: Pointer to struct config_group
+ */
+struct config_group *i3c_target_cfs_add_func_group(const char *name)
+{
+ struct config_group *group;
+
+ group = configfs_register_default_group(functions_group, name,
+ &i3c_target_func_group_type);
+ if (IS_ERR(group))
+ pr_err("failed to register configfs group for %s function\n",
+ name);
+
+ return group;
+}
+EXPORT_SYMBOL(i3c_target_cfs_add_func_group);
+
+/**
+ * i3c_target_cfs_remove_func_group() - add I3C target function group
+ * @group: group to be removed
+ */
+void i3c_target_cfs_remove_func_group(struct config_group *group)
+{
+ if (IS_ERR_OR_NULL(group))
+ return;
+
+ configfs_unregister_default_group(group);
+}
+EXPORT_SYMBOL(i3c_target_cfs_remove_func_group);
+
+static const struct config_item_type i3c_target_controllers_type = {
+ .ct_owner = THIS_MODULE,
+};
+
+static const struct config_item_type i3c_target_functions_type = {
+ .ct_owner = THIS_MODULE,
+};
+
+static const struct config_item_type i3c_target_type = {
+ .ct_owner = THIS_MODULE,
+};
+
+static struct configfs_subsystem i3c_target_cfs_subsys = {
+ .su_group = {
+ .cg_item = {
+ .ci_namebuf = "i3c_target",
+ .ci_type = &i3c_target_type,
+ },
+ },
+ .su_mutex = __MUTEX_INITIALIZER(i3c_target_cfs_subsys.su_mutex),
+};
+
+static int __init i3c_target_cfs_init(void)
+{
+ int ret;
+ struct config_group *root = &i3c_target_cfs_subsys.su_group;
+
+ config_group_init(root);
+
+ ret = configfs_register_subsystem(&i3c_target_cfs_subsys);
+ if (ret) {
+ pr_err("Error %d while registering subsystem %s\n",
+ ret, root->cg_item.ci_namebuf);
+ goto err;
+ }
+
+ functions_group = configfs_register_default_group(root, "functions",
+ &i3c_target_functions_type);
+ if (IS_ERR(functions_group)) {
+ ret = PTR_ERR(functions_group);
+ pr_err("Error %d while registering functions group\n",
+ ret);
+ goto err_functions_group;
+ }
+
+ controllers_group =
+ configfs_register_default_group(root, "controllers",
+ &i3c_target_controllers_type);
+ if (IS_ERR(controllers_group)) {
+ ret = PTR_ERR(controllers_group);
+ pr_err("Error %d while registering controllers group\n",
+ ret);
+ goto err_controllers_group;
+ }
+
+ return 0;
+
+err_controllers_group:
+ configfs_unregister_default_group(functions_group);
+
+err_functions_group:
+ configfs_unregister_subsystem(&i3c_target_cfs_subsys);
+
+err:
+ return ret;
+}
+module_init(i3c_target_cfs_init);
+
+MODULE_DESCRIPTION("I3C FUNC CONFIGFS");
+MODULE_AUTHOR("Frank Li <[email protected]>");
diff --git a/drivers/i3c/target.c b/drivers/i3c/target.c
new file mode 100644
index 0000000000000..f0bcda2c4599f
--- /dev/null
+++ b/drivers/i3c/target.c
@@ -0,0 +1,453 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * configfs to configure the I3C Slave
+ *
+ * Copyright (C) 2023 NXP
+ * Author: Frank Li <[email protected]>
+ */
+
+#include <linux/configfs.h>
+#include <linux/module.h>
+#include <linux/i3c/target.h>
+#include <linux/idr.h>
+#include <linux/slab.h>
+
+static DEFINE_MUTEX(func_lock);
+static struct class *i3c_target_ctrl_class;
+
+static void i3c_target_func_dev_release(struct device *dev)
+{
+ struct i3c_target_func *func = to_i3c_target_func(dev);
+
+ kfree(func->name);
+ kfree(func);
+}
+
+static const struct device_type i3c_target_func_type = {
+ .release = i3c_target_func_dev_release,
+};
+
+static int i3c_target_func_match_driver(struct device *dev, struct device_driver *drv)
+{
+ return !strncmp(dev_name(dev), drv->name, strlen(drv->name));
+}
+
+static int i3c_target_func_device_probe(struct device *dev)
+{
+ struct i3c_target_func *func = to_i3c_target_func(dev);
+ struct i3c_target_func_driver *driver = to_i3c_target_func_driver(dev->driver);
+
+ if (!driver->probe)
+ return -ENODEV;
+
+ func->driver = driver;
+
+ return driver->probe(func);
+}
+
+static void i3c_target_func_device_remove(struct device *dev)
+{
+ struct i3c_target_func *func = to_i3c_target_func(dev);
+ struct i3c_target_func_driver *driver = to_i3c_target_func_driver(dev->driver);
+
+ if (driver->remove)
+ driver->remove(func);
+ func->driver = NULL;
+}
+
+static const struct bus_type i3c_target_func_bus_type = {
+ .name = "i3c_target_func",
+ .probe = i3c_target_func_device_probe,
+ .remove = i3c_target_func_device_remove,
+ .match = i3c_target_func_match_driver,
+};
+
+static void i3c_target_ctrl_release(struct device *dev)
+{
+ kfree(to_i3c_target_ctrl(dev));
+}
+
+static void devm_i3c_target_ctrl_release(struct device *dev, void *res)
+{
+ struct i3c_target_ctrl *ctrl = *(struct i3c_target_ctrl **)res;
+
+ i3c_target_ctrl_destroy(ctrl);
+}
+
+struct i3c_target_ctrl *
+__devm_i3c_target_ctrl_create(struct device *dev, const struct i3c_target_ctrl_ops *ops,
+ struct module *owner)
+{
+ struct i3c_target_ctrl **ptr, *ctrl;
+
+ ptr = devres_alloc(devm_i3c_target_ctrl_release, sizeof(*ptr), GFP_KERNEL);
+ if (!ptr)
+ return ERR_PTR(-ENOMEM);
+
+ ctrl = __i3c_target_ctrl_create(dev, ops, owner);
+ if (!IS_ERR(ctrl)) {
+ *ptr = ctrl;
+ devres_add(dev, ptr);
+ } else {
+ devres_free(ptr);
+ }
+
+ return ctrl;
+}
+
+static int devm_i3c_target_ctrl_match(struct device *dev, void *res, void *match_data)
+{
+ struct i3c_target_ctrl **ptr = res;
+
+ return *ptr == match_data;
+}
+
+/**
+ * __i3c_target_ctrl_create() - create a new target controller device
+ * @dev: device that is creating the new target controller
+ * @ops: function pointers for performing target controller operations
+ * @owner: the owner of the module that creates the target controller device
+ *
+ * Return: Pointer to struct i3c_target_ctrl
+ */
+struct i3c_target_ctrl *
+__i3c_target_ctrl_create(struct device *dev, const struct i3c_target_ctrl_ops *ops,
+ struct module *owner)
+{
+ struct i3c_target_ctrl *ctrl;
+ int ret;
+
+ if (WARN_ON(!dev))
+ return ERR_PTR(-EINVAL);
+
+ ctrl = kzalloc(sizeof(*ctrl), GFP_KERNEL);
+ if (!ctrl)
+ return ERR_PTR(-ENOMEM);
+
+ device_initialize(&ctrl->dev);
+ ctrl->dev.class = i3c_target_ctrl_class;
+ ctrl->dev.parent = dev;
+ ctrl->dev.release = i3c_target_ctrl_release;
+ ctrl->ops = ops;
+
+ ret = dev_set_name(&ctrl->dev, "%s", dev_name(dev));
+ if (ret)
+ goto put_dev;
+
+ ret = device_add(&ctrl->dev);
+ if (ret)
+ goto put_dev;
+
+ ctrl->group = i3c_target_cfs_add_ctrl_group(ctrl);
+ if (!ctrl->group)
+ goto put_dev;
+
+ return ctrl;
+
+put_dev:
+ put_device(&ctrl->dev);
+ kfree(ctrl);
+
+ return ERR_PTR(ret);
+}
+EXPORT_SYMBOL_GPL(__i3c_target_ctrl_create);
+
+/**
+ * devm_i3c_target_ctrl_destroy() - destroy the target controller device
+ * @dev: device that hat has to be destroy
+ * @ctrl: the target controller device that has to be destroy
+ *
+ * Invoke to create a new target controller device and add it to i3c_target class. While at that, it
+ * also associates the device with the i3c_target using devres. On driver detach, release function
+ * is invoked on the devres data, then devres data is freed.
+ */
+void devm_i3c_target_ctrl_destroy(struct device *dev, struct i3c_target_ctrl *ctrl)
+{
+ int r;
+
+ r = devres_destroy(dev, devm_i3c_target_ctrl_release, devm_i3c_target_ctrl_match,
+ ctrl);
+ dev_WARN_ONCE(dev, r, "couldn't find I3C controller resource\n");
+}
+EXPORT_SYMBOL_GPL(devm_i3c_target_ctrl_destroy);
+
+/**
+ * i3c_target_ctrl_destroy() - destroy the target controller device
+ * @ctrl: the target controller device that has to be destroyed
+ *
+ * Invoke to destroy the I3C target device
+ */
+void i3c_target_ctrl_destroy(struct i3c_target_ctrl *ctrl)
+{
+ i3c_target_cfs_remove_ctrl_group(ctrl->group);
+ device_unregister(&ctrl->dev);
+}
+EXPORT_SYMBOL_GPL(i3c_target_ctrl_destroy);
+
+/**
+ * i3c_target_ctrl_add_func() - bind I3C target function to an target controller
+ * @ctrl: the controller device to which the target function should be added
+ * @func: the target function to be added
+ *
+ * An I3C target device can have only one functions.
+ */
+int i3c_target_ctrl_add_func(struct i3c_target_ctrl *ctrl, struct i3c_target_func *func)
+{
+ if (ctrl->func)
+ return -EBUSY;
+
+ ctrl->func = func;
+ func->ctrl = ctrl;
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(i3c_target_ctrl_add_func);
+
+/**
+ * i3c_target_ctrl_remove_func() - unbind I3C target function to an target controller
+ * @ctrl: the controller device to which the target function should be removed
+ * @func: the target function to be removed
+ *
+ * An I3C target device can have only one functions.
+ */
+void i3c_target_ctrl_remove_func(struct i3c_target_ctrl *ctrl, struct i3c_target_func *func)
+{
+ ctrl->func = NULL;
+}
+EXPORT_SYMBOL_GPL(i3c_target_ctrl_remove_func);
+
+/**
+ * i3c_target_ctrl_get() - get the I3C target controller
+ * @name: device name of the target controller
+ *
+ * Invoke to get struct i3c_target_ctrl * corresponding to the device name of the
+ * target controller
+ */
+struct i3c_target_ctrl *i3c_target_ctrl_get(const char *name)
+{
+ int ret = -EINVAL;
+ struct i3c_target_ctrl *ctrl;
+ struct device *dev;
+ struct class_dev_iter iter;
+
+ class_dev_iter_init(&iter, i3c_target_ctrl_class, NULL, NULL);
+ while ((dev = class_dev_iter_next(&iter))) {
+ if (strcmp(name, dev_name(dev)))
+ continue;
+
+ ctrl = to_i3c_target_ctrl(dev);
+ if (!try_module_get(ctrl->ops->owner)) {
+ ret = -EINVAL;
+ goto err;
+ }
+
+ class_dev_iter_exit(&iter);
+ get_device(&ctrl->dev);
+ return ctrl;
+ }
+
+err:
+ class_dev_iter_exit(&iter);
+ return ERR_PTR(ret);
+}
+EXPORT_SYMBOL_GPL(i3c_target_ctrl_get);
+
+/**
+ * i3c_target_ctrl_put() - release the I3C endpoint controller
+ * @ctrl: target controller returned by pci_target_get()
+ *
+ * release the refcount the caller obtained by invoking i3c_target_ctrl_get()
+ */
+void i3c_target_ctrl_put(struct i3c_target_ctrl *ctrl)
+{
+ if (!ctrl || IS_ERR(ctrl))
+ return;
+
+ module_put(ctrl->ops->owner);
+ put_device(&ctrl->dev);
+}
+EXPORT_SYMBOL_GPL(i3c_target_ctrl_put);
+
+/**
+ * i3c_target_ctrl_hotjoin() - trigger device hotjoin
+ * @ctrl: target controller
+ *
+ * return: 0: success, others failure
+ */
+int i3c_target_ctrl_hotjoin(struct i3c_target_ctrl *ctrl)
+{
+ if (!ctrl || IS_ERR(ctrl))
+ return -EINVAL;
+
+ if (!ctrl->ops->hotjoin)
+ return -EINVAL;
+
+ return ctrl->ops->hotjoin(ctrl);
+}
+EXPORT_SYMBOL_GPL(i3c_target_ctrl_hotjoin);
+
+/**
+ * i3c_target_func_bind() - Notify the function driver that the function device has been bound to a
+ * controller device
+ * @func: the function device which has been bound to the controller device
+ *
+ * Invoke to notify the function driver that it has been bound to a controller device
+ */
+int i3c_target_func_bind(struct i3c_target_func *func)
+{
+ struct device *dev = &func->dev;
+ int ret;
+
+ if (!func->driver) {
+ dev_WARN(dev, "func device not bound to driver\n");
+ return -EINVAL;
+ }
+
+ if (!try_module_get(func->driver->owner))
+ return -EAGAIN;
+
+ mutex_lock(&func->lock);
+ ret = func->driver->ops->bind(func);
+ if (!ret)
+ func->is_bound = true;
+ mutex_unlock(&func->lock);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(i3c_target_func_bind);
+
+/**
+ * i3c_target_func_unbind() - Notify the function driver that the binding between the function
+ * device and controller device has been lost.
+ * @func: the function device which has lost the binding with the controller device.
+ *
+ * Invoke to notify the function driver that the binding between the function device and controller
+ * device has been lost.
+ */
+void i3c_target_func_unbind(struct i3c_target_func *func)
+{
+ if (!func->driver) {
+ dev_WARN(&func->dev, "func device not bound to driver\n");
+ return;
+ }
+
+ mutex_lock(&func->lock);
+ if (func->is_bound)
+ func->driver->ops->unbind(func);
+ mutex_unlock(&func->lock);
+
+ module_put(func->driver->owner);
+}
+EXPORT_SYMBOL_GPL(i3c_target_func_unbind);
+
+/**
+ * i3c_target_func_create() - create a new I3C function device
+ * @drv_name: the driver name of the I3C function device.
+ * @name: the name of the function device.
+ *
+ * Invoke to create a new I3C function device by providing the name of the function device.
+ */
+struct i3c_target_func *i3c_target_func_create(const char *drv_name, const char *name)
+{
+ struct i3c_target_func *func;
+ struct device *dev;
+ int ret;
+
+ func = kzalloc(sizeof(*func), GFP_KERNEL);
+ if (!func)
+ return ERR_PTR(-ENOMEM);
+
+ dev = &func->dev;
+ device_initialize(dev);
+ dev->bus = &i3c_target_func_bus_type;
+ dev->type = &i3c_target_func_type;
+ mutex_init(&func->lock);
+
+ ret = dev_set_name(dev, "%s.%s", drv_name, name);
+ if (ret) {
+ put_device(dev);
+ return ERR_PTR(ret);
+ }
+
+ ret = device_add(dev);
+ if (ret) {
+ put_device(dev);
+ return ERR_PTR(ret);
+ }
+
+ return func;
+}
+EXPORT_SYMBOL_GPL(i3c_target_func_create);
+
+/**
+ * __i3c_target_func_register_driver() - register a new I3C function driver
+ * @driver: structure representing I3C function driver
+ * @owner: the owner of the module that registers the I3C function driver
+ *
+ * Invoke to register a new I3C function driver.
+ */
+int __i3c_target_func_register_driver(struct i3c_target_func_driver *driver, struct module *owner)
+{
+ int ret = -EEXIST;
+
+ if (!driver->ops)
+ return -EINVAL;
+
+ if (!driver->ops->bind || !driver->ops->unbind)
+ return -EINVAL;
+
+ driver->driver.bus = &i3c_target_func_bus_type;
+ driver->driver.owner = owner;
+
+ ret = driver_register(&driver->driver);
+ if (ret)
+ return ret;
+
+ i3c_target_cfs_add_func_group(driver->driver.name);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(__i3c_target_func_register_driver);
+
+/**
+ * i3c_target_func_unregister_driver() - unregister the I3C function driver
+ * @fd: the I3C function driver that has to be unregistered
+ *
+ * Invoke to unregister the I3C function driver.
+ */
+void i3c_target_func_unregister_driver(struct i3c_target_func_driver *fd)
+{
+ mutex_lock(&func_lock);
+ mutex_unlock(&func_lock);
+}
+EXPORT_SYMBOL_GPL(i3c_target_func_unregister_driver);
+
+static int __init i3c_target_init(void)
+{
+ int ret;
+
+ i3c_target_ctrl_class = class_create("i3c_target");
+ if (IS_ERR(i3c_target_ctrl_class)) {
+ pr_err("failed to create i3c target class --> %ld\n",
+ PTR_ERR(i3c_target_ctrl_class));
+ return PTR_ERR(i3c_target_ctrl_class);
+ }
+
+ ret = bus_register(&i3c_target_func_bus_type);
+ if (ret) {
+ class_destroy(i3c_target_ctrl_class);
+ pr_err("failed to register i3c target func bus --> %d\n", ret);
+ return ret;
+ }
+
+ return 0;
+}
+module_init(i3c_target_init);
+
+static void __exit i3c_target_exit(void)
+{
+ class_destroy(i3c_target_ctrl_class);
+ bus_unregister(&i3c_target_func_bus_type);
+}
+module_exit(i3c_target_exit);
+
diff --git a/include/linux/i3c/target.h b/include/linux/i3c/target.h
new file mode 100644
index 0000000000000..839d89565ba72
--- /dev/null
+++ b/include/linux/i3c/target.h
@@ -0,0 +1,511 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright 2023 NXP.
+ *
+ * Author: Frank Li <[email protected]>
+ */
+
+#ifndef I3C_TARGET_H
+#define I3C_TARGET_H
+
+#include <linux/device.h>
+
+struct i3c_target_func;
+struct i3c_target_ctrl;
+
+/**
+ * struct i3c_target_func_ops - set of function pointers for performing i3c target function
+ * operations
+ * @bind: ops to perform when a controller device has been bound to function device
+ * @unbind: ops to perform when a binding has been lost between a controller device and function
+ * device
+ */
+struct i3c_target_func_ops {
+ int (*bind)(struct i3c_target_func *func);
+ void (*unbind)(struct i3c_target_func *func);
+};
+
+/**
+ * struct i3c_target_func_driver - represents the I3C function driver
+ * @probe: ops to perform when a new function device has been bound to the function driver
+ * @remove: ops to perform when the binding between the function device and function driver is
+ * broken
+ * @name: I3C Function driver name
+ * @driver: I3C Function driver
+ * @ops: set of function pointers for performing function operations
+ * @owner: the owner of the module that registers the I3C function driver
+ * @epf_group: list of configfs group corresponding to the I3C function driver
+ */
+struct i3c_target_func_driver {
+ int (*probe)(struct i3c_target_func *func);
+ void (*remove)(struct i3c_target_func *func);
+
+ char *name;
+ struct device_driver driver;
+ struct i3c_target_func_ops *ops;
+ struct module *owner;
+};
+
+/**
+ * struct i3c_target_func - represents the I3C function device
+ * @dev: the I3C function device
+ * @name: the name of the I3C function device
+ * @driver: the function driver to which this function device is bound
+ * @group: configfs group associated with the EPF device
+ * @lock: mutex to protect i3c_target_func_ops
+ * @ctrl: binded I3C controller device
+ * @is_bound: indicates if bind notification to function driver has been invoked
+ * @vendor_id: vendor id
+ * @part_id: part id
+ * @instance_id: instance id
+ * @ext_id: ext id
+ * @vendor_info: vendor info
+ * @static_addr: static address for I2C. It is 0 for I3C.
+ * @max_write_len: maximum write length
+ * @max_read_len: maximum read length
+ * @bcr: bus characteristics register (BCR)
+ * @dcr: device characteristics register (DCR)
+ */
+struct i3c_target_func {
+ struct device dev;
+ char *name;
+ struct i3c_target_func_driver *driver;
+ struct config_group *group;
+ /* mutex to protect against concurrent access of i3c_target_func_ops */
+ struct mutex lock;
+ struct i3c_target_ctrl *ctrl;
+ bool is_bound;
+
+ u16 vendor_id;
+ u16 part_id;
+ u8 instance_id;
+ u16 ext_id;
+ u8 vendor_info;
+ u16 static_addr;
+ u16 max_write_len; //0 is hardware default max value
+ u16 max_read_len; //0 is hardware default max value
+ u8 bcr;
+ u8 dcr;
+};
+
+enum i3c_request_stat {
+ I3C_REQUEST_OKAY,
+ I3C_REQUEST_PARTIAL,
+ I3C_REQUEST_ERR,
+ I3C_REQUEST_CANCEL,
+};
+
+/**
+ * struct i3c_request - represents the an I3C transfer request
+ * @buf: data buffer
+ * @length: data length
+ * @complete: call back function when request finished or cancelled
+ * @context: general data for complete callback function
+ * @list: link list
+ * @status: transfer status
+ * @actual: how much actually transferred
+ * @ctrl: I3C target controller associate with this request
+ * @tx: transfer direction, 1: target to master, 0: master to target
+ */
+struct i3c_request {
+ void *buf;
+ unsigned int length;
+
+ void (*complete)(struct i3c_request *req);
+ void *context;
+ struct list_head list;
+
+ enum i3c_request_stat status;
+ unsigned int actual;
+ struct i3c_target_ctrl *ctrl;
+ bool tx;
+};
+
+/**
+ * struct i3c_target_ctrl_features - represents I3C target controller features.
+ * @tx_fifo_sz: tx hardware fifo size
+ * @rx_fifo_sz: rx hardware fifo size
+ */
+struct i3c_target_ctrl_features {
+ u32 tx_fifo_sz;
+ u32 rx_fifo_sz;
+};
+
+/**
+ * struct i3c_target_ctrl_ops - set of function pointers for performing controller operations
+ * @set_config: set I3C controller configuration
+ * @enable: enable I3C controller
+ * @disable: disable I3C controller
+ * @raise_ibi: raise IBI interrupt to master
+ * @alloc_request: allocate a i3c_request, optional, default use kmalloc
+ * @free_request: free a i3c_request, default use kfree
+ * @queue: queue an I3C transfer
+ * @dequeue: dequeue an I3C transfer
+ * @cancel_all_reqs: call all pending requests
+ * @fifo_status: current FIFO status
+ * @fifo_flush: flush hardware FIFO
+ * @hotjoin: raise hotjoin request to master
+ * @set_status_format1: set i3c status format1
+ * @get_status_format1: get i3c status format1
+ * @get_addr: get i3c dynmatic address
+ * @get_features: ops to get the features supported by the I3C target controller
+ * @owner: the module owner containing the ops
+ */
+struct i3c_target_ctrl_ops {
+ int (*set_config)(struct i3c_target_ctrl *ctrl, struct i3c_target_func *func);
+ int (*enable)(struct i3c_target_ctrl *ctrl);
+ int (*disable)(struct i3c_target_ctrl *ctrl);
+ int (*raise_ibi)(struct i3c_target_ctrl *ctrl, void *p, u8 size);
+
+ struct i3c_request *(*alloc_request)(struct i3c_target_ctrl *ctrl, gfp_t gfp_flags);
+ void (*free_request)(struct i3c_request *req);
+
+ int (*queue)(struct i3c_request *req, gfp_t gfp_flags);
+ int (*dequeue)(struct i3c_request *req);
+
+ void (*cancel_all_reqs)(struct i3c_target_ctrl *ctrl, bool tx);
+
+ int (*fifo_status)(struct i3c_target_ctrl *ctrl, bool tx);
+ void (*fifo_flush)(struct i3c_target_ctrl *ctrl, bool tx);
+ int (*hotjoin)(struct i3c_target_ctrl *ctrl);
+ int (*set_status_format1)(struct i3c_target_ctrl *ctrl, u16 status);
+ u16 (*get_status_format1)(struct i3c_target_ctrl *ctrl);
+ u8 (*get_addr)(struct i3c_target_ctrl *ctrl);
+ const struct i3c_target_ctrl_features *(*get_features)(struct i3c_target_ctrl *ctrl);
+ struct module *owner;
+};
+
+/**
+ * struct i3c_target_ctrl - represents the I3C target device
+ * @dev: I3C target device
+ * @ops: function pointers for performing endpoint operations
+ * @func: target functions present in this controller device
+ * @group: configfs group representing the I3C controller device
+ */
+struct i3c_target_ctrl {
+ struct device dev;
+ const struct i3c_target_ctrl_ops *ops;
+ struct i3c_target_func *func;
+ struct config_group *group;
+};
+
+/**
+ * i3c_target_ctrl_raise_ibi() - Raise IBI to master
+ * @ctrl: I3C target controller
+ * @p: optional data for IBI
+ * @size: size of optional data
+ *
+ * Returns: Zero for success, or an error code in case of failure
+ */
+static inline int i3c_target_ctrl_raise_ibi(struct i3c_target_ctrl *ctrl, void *p, u8 size)
+{
+ if (ctrl && ctrl->ops && ctrl->ops->raise_ibi)
+ return ctrl->ops->raise_ibi(ctrl, p, size);
+
+ return -EINVAL;
+}
+
+/**
+ * i3c_target_ctrl_cancel_all_reqs() - Cancel all pending request
+ * @ctrl: I3C target controller
+ * @tx: Transfer diretion queue
+ */
+static inline void i3c_target_ctrl_cancel_all_reqs(struct i3c_target_ctrl *ctrl, bool tx)
+{
+ if (ctrl && ctrl->ops && ctrl->ops->cancel_all_reqs)
+ ctrl->ops->cancel_all_reqs(ctrl, tx);
+}
+
+/**
+ * i3c_target_ctrl_set_config() - Set controller configuration
+ * @ctrl: I3C target controller device
+ * @func: Function device
+ *
+ * Returns: Zero for success, or an error code in case of failure
+ */
+static inline int
+i3c_target_ctrl_set_config(struct i3c_target_ctrl *ctrl, struct i3c_target_func *func)
+{
+ if (ctrl && ctrl->ops && ctrl->ops->set_config)
+ return ctrl->ops->set_config(ctrl, func);
+
+ return -EINVAL;
+}
+
+/**
+ * i3c_target_ctrl_enable() - Enable I3C controller
+ * @ctrl: I3C target controller device
+ *
+ * Returns: Zero for success, or an error code in case of failure
+ */
+static inline int
+i3c_target_ctrl_enable(struct i3c_target_ctrl *ctrl)
+{
+ if (ctrl && ctrl->ops && ctrl->ops->enable)
+ return ctrl->ops->enable(ctrl);
+
+ return -EINVAL;
+}
+
+/**
+ * i3c_target_ctrl_disable() - Disable I3C controller
+ * @ctrl: I3C target controller device
+ *
+ * Returns: Zero for success, or an error code in case of failure
+ */
+static inline int
+i3c_target_ctrl_disable(struct i3c_target_ctrl *ctrl)
+{
+ if (ctrl && ctrl->ops && ctrl->ops->disable)
+ return ctrl->ops->disable(ctrl);
+
+ return -EINVAL;
+}
+
+/**
+ * i3c_target_ctrl_alloc_request() - Alloc an I3C transfer
+ * @ctrl: I3C target controller device
+ * @gfp_flags: additional gfp flags used when allocating the buffers
+ *
+ * Returns: Zero for success, or an error code in case of failure
+ */
+static inline struct i3c_request *
+i3c_target_ctrl_alloc_request(struct i3c_target_ctrl *ctrl, gfp_t gfp_flags)
+{
+ struct i3c_request *req = NULL;
+
+ if (ctrl && ctrl->ops && ctrl->ops->alloc_request)
+ req = ctrl->ops->alloc_request(ctrl, gfp_flags);
+ else
+ req = kzalloc(sizeof(*req), gfp_flags);
+
+ if (req)
+ req->ctrl = ctrl;
+
+ return req;
+}
+
+/**
+ * i3c_target_ctrl_free_request() - Free an I3C transfer
+ * @req: I3C transfer request
+ *
+ * Returns: Zero for success, or an error code in case of failure
+ */
+static inline void
+i3c_target_ctrl_free_request(struct i3c_request *req)
+{
+ struct i3c_target_ctrl *ctrl;
+
+ if (!req)
+ return;
+
+ ctrl = req->ctrl;
+ if (ctrl && ctrl->ops && ctrl->ops->free_request)
+ ctrl->ops->free_request(req);
+ else
+ kfree(req);
+}
+
+/**
+ * i3c_target_ctrl_queue() - Queue an I3C transfer
+ * @req: I3C transfer request
+ * @gfp_flags: additional gfp flags used when allocating the buffers
+ *
+ * Returns: Zero for success, or an error code in case of failure
+ */
+static inline int
+i3c_target_ctrl_queue(struct i3c_request *req, gfp_t gfp_flags)
+{
+ struct i3c_target_ctrl *ctrl;
+ int ret = -EINVAL;
+
+ if (!req)
+ return -EINVAL;
+
+ ctrl = req->ctrl;
+
+ req->actual = 0;
+ req->status = 0;
+ if (ctrl && ctrl->ops && ctrl->ops->queue)
+ ret = ctrl->ops->queue(req, gfp_flags);
+
+ return ret;
+}
+
+/**
+ * i3c_target_ctrl_dequeue() - Dequeue an I3C transfer
+ * @req: I3C transfer request
+ *
+ * Returns: Zero for success, or an error code in case of failure
+ */
+static inline int
+i3c_target_ctrl_dequeue(struct i3c_request *req)
+{
+ struct i3c_target_ctrl *ctrl;
+ int ret = -EINVAL;
+
+ if (!req)
+ return -EINVAL;
+
+ ctrl = req->ctrl;
+ if (ctrl && ctrl->ops && ctrl->ops->dequeue)
+ ret = ctrl->ops->dequeue(req);
+
+ return ret;
+}
+
+/**
+ * i3c_target_ctrl_fifo_status() - Get controller FIFO status
+ * @ctrl: I3C target controller device
+ * @tx: 1: Target to master, 0: master to target
+ *
+ * Returns: How much data in FIFO
+ */
+static inline int
+i3c_target_ctrl_fifo_status(struct i3c_target_ctrl *ctrl, bool tx)
+{
+ if (ctrl && ctrl->ops && ctrl->ops->fifo_status)
+ return ctrl->ops->fifo_status(ctrl, tx);
+
+ return 0;
+}
+
+/**
+ * i3c_target_ctrl_fifo_flush() - Flush controller FIFO
+ * @ctrl: I3C target controller device
+ * @tx: 1: Target to master, 0: master to target
+ *
+ */
+static inline void
+i3c_target_ctrl_fifo_flush(struct i3c_target_ctrl *ctrl, bool tx)
+{
+ if (ctrl && ctrl->ops && ctrl->ops->fifo_flush)
+ return ctrl->ops->fifo_flush(ctrl, tx);
+}
+
+/**
+ * i3c_target_ctrl_get_features() - Get controller supported features
+ * @ctrl: I3C target controller device
+ *
+ * Returns: The pointer to struct i3c_target_ctrl_features
+ */
+static inline const struct i3c_target_ctrl_features*
+i3c_target_ctrl_get_features(struct i3c_target_ctrl *ctrl)
+{
+ if (ctrl && ctrl->ops && ctrl->ops->get_features)
+ return ctrl->ops->get_features(ctrl);
+
+ return NULL;
+}
+
+/**
+ * i3c_target_ctrl_set_status_format1() - Set controller supported features
+ * @ctrl: I3C target controller device
+ * @status: I3C GETSTATUS format1
+ *
+ * Returns: Zero for success, or an error code in case of failure
+ */
+static inline int
+i3c_target_ctrl_set_status_format1(struct i3c_target_ctrl *ctrl, u16 status)
+{
+ if (ctrl && ctrl->ops && ctrl->ops->set_status_format1)
+ return ctrl->ops->set_status_format1(ctrl, status);
+
+ return -EINVAL;
+}
+
+/**
+ * i3c_target_ctrl_get_status_format1() - Get controller supported features
+ * @ctrl: I3C target controller device
+ *
+ * Return: I3C GETSTATUS format1
+ */
+static inline u16
+i3c_target_ctrl_get_status_format1(struct i3c_target_ctrl *ctrl)
+{
+ if (ctrl && ctrl->ops && ctrl->ops->get_status_format1)
+ return ctrl->ops->get_status_format1(ctrl);
+
+ return 0;
+}
+
+/**
+ * i3c_target_ctrl_get_addr() - Get controller address
+ * @ctrl: I3C target controller device
+ *
+ * Return: address
+ */
+static inline u8 i3c_target_ctrl_get_addr(struct i3c_target_ctrl *ctrl)
+{
+ if (ctrl && ctrl->ops && ctrl->ops->get_addr)
+ return ctrl->ops->get_addr(ctrl);
+
+ return 0;
+}
+
+#define to_i3c_target_ctrl(device) container_of((device), struct i3c_target_ctrl, dev)
+
+#define to_i3c_target_func(func_dev) container_of((func_dev), struct i3c_target_func, dev)
+#define to_i3c_target_func_driver(drv) (container_of((drv), struct i3c_target_func_driver, driver))
+
+#define i3c_target_ctrl_create(dev, ops) \
+ __i3c_target_ctrl_create((dev), (ops), THIS_MODULE)
+#define devm_i3c_target_ctrl_create(dev, ops) \
+ __devm_i3c_target_ctrl_create((dev), (ops), THIS_MODULE)
+
+struct i3c_target_ctrl *
+__devm_i3c_target_ctrl_create(struct device *dev, const struct i3c_target_ctrl_ops *ops,
+ struct module *owner);
+struct i3c_target_ctrl *
+__i3c_target_ctrl_create(struct device *dev, const struct i3c_target_ctrl_ops *ops,
+ struct module *owner);
+
+void devm_i3c_target_ctrl_destroy(struct device *dev, struct i3c_target_ctrl *epc);
+void i3c_target_ctrl_destroy(struct i3c_target_ctrl *epc);
+
+int i3c_target_ctrl_add_func(struct i3c_target_ctrl *ctrl, struct i3c_target_func *func);
+void i3c_target_ctrl_remove_func(struct i3c_target_ctrl *ctrl, struct i3c_target_func *func);
+int i3c_target_ctrl_hotjoin(struct i3c_target_ctrl *ctrl);
+
+struct config_group *i3c_target_cfs_add_ctrl_group(struct i3c_target_ctrl *ctrl);
+
+void i3c_target_cfs_remove_ctrl_group(struct config_group *group);
+struct config_group *i3c_target_cfs_add_func_group(const char *name);
+void i3c_target_cfs_remove_func_group(struct config_group *group);
+struct i3c_target_ctrl *i3c_target_ctrl_get(const char *name);
+void i3c_target_ctrl_put(struct i3c_target_ctrl *ctrl);
+
+int i3c_target_func_bind(struct i3c_target_func *func);
+void i3c_target_func_unbind(struct i3c_target_func *func);
+struct i3c_target_func *i3c_target_func_create(const char *drv_name, const char *name);
+
+#define i3c_target_func_register_driver(drv) \
+ __i3c_target_func_register_driver(drv, THIS_MODULE)
+
+int __i3c_target_func_register_driver(struct i3c_target_func_driver *drv, struct module *owner);
+void i3c_target_func_unregister_driver(struct i3c_target_func_driver *drv);
+
+#define DECLARE_I3C_TARGET_FUNC(_name, _probe, _remove, _ops) \
+ static struct i3c_target_func_driver _name ## i3c_func = { \
+ .driver.name = __stringify(_name), \
+ .owner = THIS_MODULE, \
+ .probe = _probe, \
+ .remove = _remove, \
+ .ops = _ops \
+ }; \
+ MODULE_ALIAS("i3cfunc:" __stringify(_name))
+
+#define DECLARE_I3C_TARGET_INIT(_name, _probe, _remove, _ops) \
+ DECLARE_I3C_TARGET_FUNC(_name, _probe, _remove, _ops); \
+ static int __init _name ## mod_init(void) \
+ { \
+ return i3c_target_func_register_driver(&_name ## i3c_func); \
+ } \
+ static void __exit _name ## mod_exit(void) \
+ { \
+ i3c_target_func_unregister_driver(&_name ## i3c_func); \
+ } \
+ module_init(_name ## mod_init); \
+ module_exit(_name ## mod_exit)
+
+#endif
--
2.34.1


2024-01-10 17:54:16

by Frank Li

[permalink] [raw]
Subject: [PATCH v2 4/7] i3c: target: add svc target controller support

Add Silvaco I3C target controller support

Signed-off-by: Frank Li <[email protected]>
---
drivers/i3c/Kconfig | 3 +
drivers/i3c/Makefile | 1 +
drivers/i3c/target/Kconfig | 9 +
drivers/i3c/target/Makefile | 4 +
drivers/i3c/target/svc-i3c-target.c | 795 ++++++++++++++++++++++++++++
5 files changed, 812 insertions(+)
create mode 100644 drivers/i3c/target/Kconfig
create mode 100644 drivers/i3c/target/Makefile
create mode 100644 drivers/i3c/target/svc-i3c-target.c

diff --git a/drivers/i3c/Kconfig b/drivers/i3c/Kconfig
index d59a7eb83d13a..08ceef313f831 100644
--- a/drivers/i3c/Kconfig
+++ b/drivers/i3c/Kconfig
@@ -48,3 +48,6 @@ config I3C_TARGET_CONFIGFS
the target function and used to bind the function with a target
controller.

+if I3C_TARGET
+source "drivers/i3c/target/Kconfig"
+endif # I3C_TARGET
diff --git a/drivers/i3c/Makefile b/drivers/i3c/Makefile
index 475afb40429e0..c36455cb852ea 100644
--- a/drivers/i3c/Makefile
+++ b/drivers/i3c/Makefile
@@ -4,3 +4,4 @@ obj-$(CONFIG_I3C) += i3c.o
obj-$(CONFIG_I3C) += master/
obj-$(CONFIG_I3C_TARGET) += target.o
obj-$(CONFIG_I3C_TARGET_CONFIGFS) += i3c-cfs.o
+obj-$(CONFIG_I3C_TARGET) += target/
diff --git a/drivers/i3c/target/Kconfig b/drivers/i3c/target/Kconfig
new file mode 100644
index 0000000000000..6b6307117caab
--- /dev/null
+++ b/drivers/i3c/target/Kconfig
@@ -0,0 +1,9 @@
+# SPDX-License-Identifier: GPL-2.0
+
+config I3C_TARGET_CTRL_SVC
+ tristate "Silvaco I3C Dual-Role Target driver"
+ depends on I3C
+ depends on HAS_IOMEM
+ depends on !(ALPHA || PARISC)
+ help
+ Support for Silvaco I3C Dual-Role Target Controller.
diff --git a/drivers/i3c/target/Makefile b/drivers/i3c/target/Makefile
new file mode 100644
index 0000000000000..10e160f66e3dc
--- /dev/null
+++ b/drivers/i3c/target/Makefile
@@ -0,0 +1,4 @@
+# SPDX-License-Identifier: GPL-2.0
+
+obj-${CONFIG_I3C_TARGET_CTRL_SVC} += svc-i3c-target.o
+
diff --git a/drivers/i3c/target/svc-i3c-target.c b/drivers/i3c/target/svc-i3c-target.c
new file mode 100644
index 0000000000000..1bedf840525a5
--- /dev/null
+++ b/drivers/i3c/target/svc-i3c-target.c
@@ -0,0 +1,795 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright 2023 NXP.
+ *
+ * Author: Frank Li <[email protected]>
+ */
+
+#include <linux/bitfield.h>
+#include <linux/clk.h>
+#include <linux/completion.h>
+#include <linux/errno.h>
+#include <linux/i3c/target.h>
+#include <linux/i3c/target.h>
+#include <linux/interrupt.h>
+#include <linux/iopoll.h>
+#include <linux/list.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/pinctrl/consumer.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+#include <linux/clk.h>
+#include <linux/console.h>
+#include <linux/i3c/device.h>
+#include <linux/kernel.h>
+#include <linux/mod_devicetable.h>
+
+enum i3c_clks {
+ PCLK,
+ FCLK,
+ SCLK,
+ MAXCLK,
+};
+
+struct svc_i3c_target {
+ struct device *dev;
+ void __iomem *regs;
+ int irq;
+ struct clk_bulk_data clks[MAXCLK];
+
+ struct list_head txq;
+ spinlock_t txq_lock; /* protect tx queue */
+ struct list_head rxq;
+ spinlock_t rxq_lock; /* protect rx queue */
+ struct list_head cq;
+ spinlock_t cq_lock; /* protect complete queue */
+
+ struct work_struct work;
+ struct workqueue_struct *workqueue;
+
+ struct completion dacomplete;
+ struct i3c_target_ctrl_features features;
+
+ spinlock_t ctrl_lock; /* protext access SCTRL register */
+};
+
+#define I3C_SCONFIG 0x4
+#define I3C_SCONFIG_SLVENA_MASK BIT(0)
+#define I3C_SCONFIG_OFFLINE_MASK BIT(9)
+#define I3C_SCONFIG_SADDR_MASK GENMASK(31, 25)
+
+#define I3C_SSTATUS 0x8
+#define I3C_SSTATUS_STNOTSTOP_MASK BIT(0)
+#define I3C_SSTATUS_STOP_MASK BIT(10)
+#define I3C_SSTATUS_RX_PEND_MASK BIT(11)
+#define I3C_SSTATUS_TXNOTFULL_MASK BIT(12)
+#define I3C_SSTATUS_DACHG_MASK BIT(13)
+#define I3C_SSTATUS_EVDET_MASK GENMASK(21, 20)
+#define I3C_SSTATUS_EVDET_ACKED 0x3
+#define I3C_SSTATUS_IBIDIS_MASK BIT(24)
+#define I3C_SSTATUS_HJDIS_MASK BIT(27)
+
+#define I3C_SCTRL 0xc
+#define I3C_SCTRL_EVENT_MASK GENMASK(1, 0)
+#define I3C_SCTRL_EVENT_IBI 0x1
+#define I3C_SCTRL_EVENT_HOTJOIN 0x3
+#define I3C_SCTRL_EXTDATA_MASK BIT(3)
+#define I3C_SCTRL_IBIDATA_MASK GENMASK(15, 8)
+
+#define I3C_SINTSET 0x10
+#define I3C_SINTCLR 0x14
+#define I3C_SINT_START BIT(8)
+#define I3C_SINT_MATCHED BIT(9)
+#define I3C_SINT_STOP BIT(10)
+#define I3C_SINT_RXPEND BIT(11)
+#define I3C_SINT_TXSEND BIT(12)
+#define I3C_SINT_DACHG BIT(13)
+#define I3C_SINT_CCC BIT(14)
+#define I3C_SINT_ERRWARN BIT(15)
+#define I3C_SINT_DDRMAATCHED BIT(16)
+#define I3C_SINT_CHANDLED BIT(17)
+#define I3C_SINT_EVENT BIT(18)
+#define I3C_SINT_SLVRST BIT(19)
+
+#define I3C_SDATACTRL 0x2c
+#define I3C_SDATACTRL_RXEMPTY_MASK BIT(31)
+#define I3C_SDATACTRL_TXFULL_MASK BIT(30)
+#define I3C_SDATACTRL_RXCOUNT_MASK GENMASK(28, 24)
+#define I3C_SDATACTRL_TXCOUNT_MASK GENMASK(20, 16)
+#define I3C_SDATACTRL_FLUSHFB_MASK BIT(1)
+#define I3C_SDATACTRL_FLUSHTB_MASK BIT(0)
+
+#define I3C_SWDATAB 0x30
+#define I3C_SWDATAB_END_ALSO_MASK BIT(16)
+#define I3C_SWDATAB_END_MASK BIT(8)
+
+#define I3C_SWDATAE 0x34
+#define I3C_SRDATAB 0x40
+
+#define I3C_SCAPABILITIES 0x60
+#define I3C_SCAPABILITIES_FIFOTX_MASK GENMASK(27, 26)
+#define I3C_SCAPABILITIES_FIFORX_MASK GENMASK(29, 28)
+
+#define I3C_SMAXLIMITS 0x68
+#define I3C_SMAXLIMITS_MAXRD_MASK GENMASK(11, 0)
+#define I3C_SMAXLIMITS_MAXWR_MASK GENMASK(27, 16)
+
+#define I3C_SIDPARTNO 0x6c
+
+#define I3C_SIDEXT 0x70
+#define I3C_SIDEXT_BCR_MASK GENMASK(23, 16)
+#define I3C_SIDEXT_DCR_MASK GENMASK(15, 8)
+#define I3C_SVENDORID 0x74
+
+#define I3C_SMAPCTRL0 0x11c
+#define I3C_SMAPCTRL0_ENA_MASK BIT(0)
+#define I3C_SMAPCTRL0_DA_MASK GENMASK(7, 1)
+
+#define I3C_IBIEXT1 0x140
+#define I3C_IBIEXT1_CNT_MASK GEN_MASK(2, 0)
+#define I3C_IBIEXT1_MAX_MASK GEN_MASK(4, 6)
+#define I3C_IBIEXT1_EXT1_SHIFT 8
+#define I3C_IBIEXT1_EXT2_SHIFT 16
+#define I3C_IBIEXT1_EXT3_SHIFT 24
+
+#define I3C_IBIEXT2 0x144
+#define I3C_IBIEXT2_EXT4_SHIFT 0
+#define I3C_IBIEXT2_EXT5_SHIFT 8
+#define I3C_IBIEXT2_EXT6_SHIFT 16
+#define I3C_IBIEXT2_EXT7_SHIFT 24
+
+static int svc_i3c_target_enable(struct i3c_target_ctrl *ctrl)
+{
+ struct svc_i3c_target *svc;
+ u32 val;
+
+ svc = dev_get_drvdata(&ctrl->dev);
+
+ val = readl_relaxed(svc->regs + I3C_SCONFIG);
+ val |= I3C_SCONFIG_SLVENA_MASK;
+ writel_relaxed(val, svc->regs + I3C_SCONFIG);
+
+ return 0;
+}
+
+static int svc_i3c_target_disable(struct i3c_target_ctrl *ctrl)
+{
+ struct svc_i3c_target *svc;
+ u32 val;
+
+ svc = dev_get_drvdata(&ctrl->dev);
+
+ val = readl_relaxed(svc->regs + I3C_SCONFIG);
+ val &= ~I3C_SCONFIG_SLVENA_MASK;
+ writel_relaxed(val, svc->regs + I3C_SCONFIG);
+
+ return 0;
+}
+
+static int svc_i3c_target_set_config(struct i3c_target_ctrl *ctrl, struct i3c_target_func *func)
+{
+ struct svc_i3c_target *svc;
+ u32 val;
+ u32 wm, rm;
+
+ svc = dev_get_drvdata(&ctrl->dev);
+
+ if (func->static_addr > 0x7F)
+ return -EINVAL;
+
+ val = readl_relaxed(svc->regs + I3C_SCONFIG);
+ val &= ~I3C_SCONFIG_SLVENA_MASK;
+ val |= FIELD_PREP(I3C_SCONFIG_SADDR_MASK, func->static_addr);
+ writel_relaxed(val, svc->regs + I3C_SCONFIG);
+
+ if (func->part_id)
+ writel_relaxed((func->part_id << 16) |
+ ((func->instance_id << 12) & GENMASK(15, 12)) |
+ (func->ext_id & GENMASK(11, 0)), svc->regs + I3C_SIDPARTNO);
+
+ writel_relaxed(FIELD_PREP(I3C_SIDEXT_BCR_MASK, func->bcr) |
+ FIELD_PREP(I3C_SIDEXT_DCR_MASK, func->dcr),
+ svc->regs + I3C_SIDEXT);
+
+ wm = func->max_write_len == 0 ?
+ FIELD_GET(I3C_SMAXLIMITS_MAXWR_MASK, I3C_SMAXLIMITS_MAXWR_MASK) : func->max_write_len;
+
+ wm = max_t(u32, val, 8);
+
+ rm = func->max_read_len == 0 ?
+ FIELD_GET(I3C_SMAXLIMITS_MAXRD_MASK, I3C_SMAXLIMITS_MAXRD_MASK) : func->max_read_len;
+ rm = max_t(u32, val, 16);
+
+ val = FIELD_PREP(I3C_SMAXLIMITS_MAXRD_MASK, rm) | FIELD_PREP(I3C_SMAXLIMITS_MAXWR_MASK, wm);
+ writel_relaxed(val, svc->regs + I3C_SMAXLIMITS);
+
+ writel_relaxed(func->vendor_id, svc->regs + I3C_SVENDORID);
+ return 0;
+}
+
+const struct i3c_target_ctrl_features *svc_i3c_get_features(struct i3c_target_ctrl *ctrl)
+{
+ struct svc_i3c_target *svc;
+
+ svc = dev_get_drvdata(&ctrl->dev);
+
+ if (!svc)
+ return NULL;
+
+ return &svc->features;
+}
+
+static void svc_i3c_queue_complete(struct svc_i3c_target *svc, struct i3c_request *complete)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&svc->cq_lock, flags);
+ list_add_tail(&complete->list, &svc->cq);
+ spin_unlock_irqrestore(&svc->cq_lock, flags);
+ queue_work(svc->workqueue, &svc->work);
+}
+
+static void svc_i3c_fill_txfifo(struct svc_i3c_target *svc)
+{
+ struct i3c_request *req, *complete = NULL;
+ unsigned long flags;
+ int val;
+
+ spin_lock_irqsave(&svc->txq_lock, flags);
+ while ((!!(req = list_first_entry_or_null(&svc->txq, struct i3c_request, list))) &&
+ !((readl_relaxed(svc->regs + I3C_SDATACTRL) & I3C_SDATACTRL_TXFULL_MASK))) {
+ while (!(readl_relaxed(svc->regs + I3C_SDATACTRL)
+ & I3C_SDATACTRL_TXFULL_MASK)) {
+ val = *(u8 *)(req->buf + req->actual);
+
+ if (req->actual + 1 == req->length)
+ writel_relaxed(val, svc->regs + I3C_SWDATAE);
+ else
+ writel_relaxed(val, svc->regs + I3C_SWDATAB);
+
+ req->actual++;
+
+ if (req->actual == req->length) {
+ list_del(&req->list);
+ complete = req;
+ spin_unlock_irqrestore(&svc->txq_lock, flags);
+
+ svc_i3c_queue_complete(svc, complete);
+
+ spin_lock_irqsave(&svc->txq_lock, flags);
+ break;
+ }
+ }
+ }
+ spin_unlock_irqrestore(&svc->txq_lock, flags);
+}
+
+static int svc_i3c_target_queue(struct i3c_request *req, gfp_t)
+{
+ struct svc_i3c_target *svc;
+ struct list_head *q;
+ unsigned long flags;
+ spinlock_t *lk;
+
+ svc = dev_get_drvdata(&req->ctrl->dev);
+ if (!svc)
+ return -EINVAL;
+
+ if (req->tx) {
+ q = &svc->txq;
+ lk = &svc->txq_lock;
+ } else {
+ q = &svc->rxq;
+ lk = &svc->rxq_lock;
+ }
+
+ spin_lock_irqsave(lk, flags);
+ list_add_tail(&req->list, q);
+ spin_unlock_irqrestore(lk, flags);
+
+ if (req->tx)
+ svc_i3c_fill_txfifo(svc);
+
+ if (req->tx)
+ writel_relaxed(I3C_SINT_TXSEND, svc->regs + I3C_SINTSET);
+ else
+ writel_relaxed(I3C_SINT_RXPEND, svc->regs + I3C_SINTSET);
+
+ return 0;
+}
+
+static int svc_i3c_dequeue(struct i3c_request *req)
+{
+ struct svc_i3c_target *svc;
+ unsigned long flags;
+ spinlock_t *lk;
+
+ svc = dev_get_drvdata(&req->ctrl->dev);
+ if (!svc)
+ return -EINVAL;
+
+ if (req->tx)
+ lk = &svc->txq_lock;
+ else
+ lk = &svc->rxq_lock;
+
+ spin_lock_irqsave(lk, flags);
+ list_del(&req->list);
+ spin_unlock_irqrestore(lk, flags);
+
+ return 0;
+}
+
+static void svc_i3c_target_fifo_flush(struct i3c_target_ctrl *ctrl, bool tx)
+{
+ struct svc_i3c_target *svc;
+ u32 val;
+
+ svc = dev_get_drvdata(&ctrl->dev);
+
+ val = readl_relaxed(svc->regs + I3C_SDATACTRL);
+
+ val |= tx ? I3C_SDATACTRL_FLUSHTB_MASK : I3C_SDATACTRL_FLUSHFB_MASK;
+
+ writel_relaxed(val, svc->regs + I3C_SDATACTRL);
+}
+
+static int
+svc_i3c_target_raise_ibi(struct i3c_target_ctrl *ctrl, void *p, u8 size)
+{
+ struct svc_i3c_target *svc;
+ unsigned long flags;
+ u8 *ibidata = p;
+ u32 ext1 = 0, ext2 = 0;
+ u32 val;
+ int ret;
+
+ svc = dev_get_drvdata(&ctrl->dev);
+
+ if (size && !p)
+ return -EINVAL;
+
+ if (size > 8)
+ return -EINVAL;
+
+ val = readl_relaxed(svc->regs + I3C_SSTATUS);
+ if (val & I3C_SSTATUS_IBIDIS_MASK)
+ return -EINVAL;
+
+ ret = readl_relaxed_poll_timeout(svc->regs + I3C_SCTRL, val,
+ !(val & I3C_SCTRL_EVENT_MASK), 0, 10000);
+ if (ret) {
+ dev_err(&ctrl->dev, "Timeout when polling for NO event pending");
+ val &= ~I3C_SCTRL_EVENT_MASK;
+ writel_relaxed(val, svc->regs + I3C_SCTRL);
+ return -ENAVAIL;
+ }
+
+ spin_lock_irqsave(&svc->ctrl_lock, flags);
+
+ val = readl_relaxed(svc->regs + I3C_SCTRL);
+
+ val &= ~I3C_SCTRL_EVENT_MASK | I3C_SCTRL_IBIDATA_MASK;
+ val |= FIELD_PREP(I3C_SCTRL_EVENT_MASK, I3C_SCTRL_EVENT_IBI);
+
+ if (size) {
+ val |= FIELD_PREP(I3C_SCTRL_IBIDATA_MASK, *ibidata);
+ ibidata++;
+
+ if (size > 1)
+ val |= I3C_SCTRL_EXTDATA_MASK;
+
+ size--;
+ if (size > 0) {
+ ext1 |= (size + 2);
+ ext1 |= (*ibidata++) << I3C_IBIEXT1_EXT1_SHIFT;
+ size--;
+ }
+
+ if (size > 0) {
+ ext1 |= (*ibidata++) << I3C_IBIEXT1_EXT2_SHIFT;
+ size--;
+ }
+
+ if (size > 0) {
+ ext1 |= (*ibidata++) << I3C_IBIEXT1_EXT3_SHIFT;
+ size--;
+ }
+
+ writel_relaxed(ext1, svc->regs + I3C_IBIEXT1);
+
+ if (size > 0) {
+ ext2 |= (*ibidata++) << I3C_IBIEXT2_EXT4_SHIFT;
+ size--;
+ }
+
+ if (size > 0) {
+ ext2 |= (*ibidata++) << I3C_IBIEXT2_EXT5_SHIFT;
+ size--;
+ }
+
+ if (size > 0) {
+ ext2 |= (*ibidata++) << I3C_IBIEXT2_EXT6_SHIFT;
+ size--;
+ }
+
+ if (size > 0) {
+ ext2 |= (*ibidata++) << I3C_IBIEXT2_EXT7_SHIFT;
+ size--;
+ }
+
+ writeb_relaxed(ext2, svc->regs + I3C_IBIEXT2);
+ }
+
+ /* Issue IBI*/
+ writel_relaxed(val, svc->regs + I3C_SCTRL);
+ spin_unlock_irqrestore(&svc->ctrl_lock, flags);
+
+ ret = readl_relaxed_poll_timeout(svc->regs + I3C_SCTRL, val,
+ !(val & I3C_SCTRL_EVENT_MASK), 0, 1000000);
+ if (ret) {
+ dev_err(&ctrl->dev, "Timeout when polling for IBI finish\n");
+
+ //clear event to above hang bus
+ spin_lock_irqsave(&svc->ctrl_lock, flags);
+ val = readl_relaxed(svc->regs + I3C_SCTRL);
+ val &= ~I3C_SCTRL_EVENT_MASK;
+ writel_relaxed(val, svc->regs + I3C_SCTRL);
+ spin_unlock_irqrestore(&svc->ctrl_lock, flags);
+
+ return -ENAVAIL;
+ }
+
+ return 0;
+}
+
+static void svc_i3c_target_complete(struct work_struct *work)
+{
+ struct svc_i3c_target *svc = container_of(work, struct svc_i3c_target, work);
+ struct i3c_request *req;
+ unsigned long flags;
+
+ spin_lock_irqsave(&svc->cq_lock, flags);
+ while (!list_empty(&svc->cq)) {
+ req = list_first_entry(&svc->cq, struct i3c_request, list);
+ list_del(&req->list);
+ spin_unlock_irqrestore(&svc->cq_lock, flags);
+ req->complete(req);
+
+ spin_lock_irqsave(&svc->cq_lock, flags);
+ }
+ spin_unlock_irqrestore(&svc->cq_lock, flags);
+}
+
+static irqreturn_t svc_i3c_target_irq_handler(int irq, void *dev_id)
+{
+ struct i3c_request *req, *complete = NULL;
+ struct svc_i3c_target *svc = dev_id;
+ unsigned long flags;
+ u32 statusFlags;
+
+ statusFlags = readl(svc->regs + I3C_SSTATUS);
+ writel(statusFlags, svc->regs + I3C_SSTATUS);
+
+ if (statusFlags & I3C_SSTATUS_DACHG_MASK)
+ complete_all(&svc->dacomplete);
+
+ if (statusFlags & I3C_SSTATUS_RX_PEND_MASK) {
+ spin_lock_irqsave(&svc->rxq_lock, flags);
+ req = list_first_entry_or_null(&svc->rxq, struct i3c_request, list);
+
+ if (!req) {
+ writel_relaxed(I3C_SINT_RXPEND, svc->regs + I3C_SINTCLR);
+ } else {
+ while (!(readl_relaxed(svc->regs + I3C_SDATACTRL) &
+ I3C_SDATACTRL_RXEMPTY_MASK)) {
+ *(u8 *)(req->buf + req->actual) =
+ readl_relaxed(svc->regs + I3C_SRDATAB);
+ req->actual++;
+
+ if (req->actual == req->length) {
+ complete = req;
+ list_del(&req->list);
+ break;
+ }
+ }
+
+ if (req->actual != req->length && (statusFlags & I3C_SSTATUS_STOP_MASK)) {
+ complete = req;
+ list_del(&req->list);
+ }
+ }
+ spin_unlock_irqrestore(&svc->rxq_lock, flags);
+
+ if (complete) {
+ spin_lock_irqsave(&svc->cq_lock, flags);
+ list_add_tail(&complete->list, &svc->cq);
+ spin_unlock_irqrestore(&svc->cq_lock, flags);
+ queue_work(svc->workqueue, &svc->work);
+ complete = NULL;
+ }
+ }
+
+ if (statusFlags & I3C_SSTATUS_TXNOTFULL_MASK) {
+ svc_i3c_fill_txfifo(svc);
+
+ spin_lock_irqsave(&svc->txq_lock, flags);
+ if (list_empty(&svc->txq))
+ writel_relaxed(I3C_SINT_TXSEND, svc->regs + I3C_SINTCLR);
+ spin_unlock_irqrestore(&svc->txq_lock, flags);
+ }
+
+ return IRQ_HANDLED;
+}
+
+static void svc_i3c_cancel_all_reqs(struct i3c_target_ctrl *ctrl, bool tx)
+{
+ struct svc_i3c_target *svc;
+ struct i3c_request *req;
+ struct list_head *q;
+ unsigned long flags;
+ spinlock_t *lk;
+
+ svc = dev_get_drvdata(&ctrl->dev);
+ if (!svc)
+ return;
+
+ if (tx) {
+ q = &svc->txq;
+ lk = &svc->txq_lock;
+ } else {
+ q = &svc->rxq;
+ lk = &svc->rxq_lock;
+ }
+
+ spin_lock_irqsave(lk, flags);
+ while (!list_empty(q)) {
+ req = list_first_entry(q, struct i3c_request, list);
+ list_del(&req->list);
+ spin_unlock_irqrestore(lk, flags);
+
+ req->status = I3C_REQUEST_CANCEL;
+ req->complete(req);
+ spin_lock_irqsave(lk, flags);
+ }
+ spin_unlock_irqrestore(lk, flags);
+}
+
+static int svc_i3c_hotjoin(struct i3c_target_ctrl *ctrl)
+{
+ struct svc_i3c_target *svc;
+ int ret;
+ u32 val;
+ u32 cfg;
+
+ svc = dev_get_drvdata(&ctrl->dev);
+ if (!svc)
+ return -EINVAL;
+
+ reinit_completion(&svc->dacomplete);
+
+ val = readl_relaxed(svc->regs + I3C_SSTATUS);
+ if (val & I3C_SSTATUS_HJDIS_MASK) {
+ dev_err(&ctrl->dev, "Hotjoin disabled by i3c master\n");
+ return -EINVAL;
+ }
+
+ ret = readl_relaxed_poll_timeout(svc->regs + I3C_SCTRL, val,
+ !(val & I3C_SCTRL_EVENT_MASK), 0, 10000);
+ if (ret) {
+ dev_err(&ctrl->dev, "Timeout when polling for none event pending");
+ return -ENAVAIL;
+ }
+
+ cfg = readl_relaxed(svc->regs + I3C_SCONFIG);
+ cfg |= I3C_SCONFIG_OFFLINE_MASK;
+ writel_relaxed(cfg, svc->regs + I3C_SCONFIG);
+
+ val &= ~(I3C_SCTRL_EVENT_MASK | I3C_SCTRL_IBIDATA_MASK);
+ val |= FIELD_PREP(I3C_SCTRL_EVENT_MASK, I3C_SCTRL_EVENT_HOTJOIN);
+ /* Issue hotjoin*/
+ writel_relaxed(val, svc->regs + I3C_SCTRL);
+
+ ret = readl_relaxed_poll_timeout(svc->regs + I3C_SCTRL, val,
+ !(val & I3C_SCTRL_EVENT_MASK), 0, 100000);
+ if (ret) {
+ val &= ~FIELD_PREP(I3C_SCTRL_EVENT_MASK, I3C_SCTRL_EVENT_MASK);
+ writel_relaxed(val, svc->regs + I3C_SCTRL);
+ dev_err(&ctrl->dev, "Timeout when polling for HOTJOIN finish\n");
+ return -EINVAL;
+ }
+
+ val = readl_relaxed(svc->regs + I3C_SSTATUS);
+ val = FIELD_GET(I3C_SSTATUS_EVDET_MASK, val);
+ if (val != I3C_SSTATUS_EVDET_ACKED) {
+ dev_err(&ctrl->dev, "Master NACKED hotjoin request\n");
+ return -EINVAL;
+ }
+
+ writel_relaxed(I3C_SINT_DACHG, svc->regs + I3C_SINTSET);
+ ret = wait_for_completion_timeout(&svc->dacomplete, msecs_to_jiffies(100));
+ writel_relaxed(I3C_SINT_DACHG, svc->regs + I3C_SINTCLR);
+ if (!ret) {
+ dev_err(&ctrl->dev, "wait for da assignment timeout\n");
+ return -EIO;
+ }
+
+ val = readl_relaxed(svc->regs + I3C_SMAPCTRL0);
+ val = FIELD_GET(I3C_SMAPCTRL0_DA_MASK, val);
+ dev_info(&ctrl->dev, "Get dynamtic address 0x%x\n", val);
+ return 0;
+}
+
+static int svc_i3c_set_status_format1(struct i3c_target_ctrl *ctrl, u16 status)
+{
+ struct svc_i3c_target *svc;
+ unsigned long flags;
+ u32 val;
+
+ svc = dev_get_drvdata(&ctrl->dev);
+
+ spin_lock_irqsave(&svc->ctrl_lock, flags);
+ val = readl_relaxed(svc->regs + I3C_SCTRL);
+ val &= 0xFFFF;
+ val |= status << 16;
+ writel_relaxed(val, svc->regs + I3C_SCTRL);
+ spin_unlock_irqrestore(&svc->ctrl_lock, flags);
+
+ return 0;
+}
+
+static u16 svc_i3c_get_status_format1(struct i3c_target_ctrl *ctrl)
+{
+ struct svc_i3c_target *svc;
+
+ svc = dev_get_drvdata(&ctrl->dev);
+
+ return readl_relaxed(svc->regs + I3C_SCTRL) >> 16;
+}
+
+static u8 svc_i3c_get_addr(struct i3c_target_ctrl *ctrl)
+{
+ struct svc_i3c_target *svc;
+ int val;
+
+ svc = dev_get_drvdata(&ctrl->dev);
+
+ val = readl_relaxed(svc->regs + I3C_SMAPCTRL0);
+
+ if (val & I3C_SMAPCTRL0_ENA_MASK)
+ return FIELD_GET(I3C_SMAPCTRL0_DA_MASK, val);
+
+ return 0;
+}
+
+int svc_i3c_fifo_status(struct i3c_target_ctrl *ctrl, bool tx)
+{
+ struct svc_i3c_target *svc;
+ int val;
+
+ svc = dev_get_drvdata(&ctrl->dev);
+
+ val = readl_relaxed(svc->regs + I3C_SDATACTRL);
+
+ if (tx)
+ return FIELD_GET(I3C_SDATACTRL_TXCOUNT_MASK, val);
+ else
+ return FIELD_GET(I3C_SDATACTRL_RXCOUNT_MASK, val);
+}
+
+static struct i3c_target_ctrl_ops svc_i3c_target_ops = {
+ .set_config = svc_i3c_target_set_config,
+ .enable = svc_i3c_target_enable,
+ .disable = svc_i3c_target_disable,
+ .queue = svc_i3c_target_queue,
+ .dequeue = svc_i3c_dequeue,
+ .raise_ibi = svc_i3c_target_raise_ibi,
+ .fifo_flush = svc_i3c_target_fifo_flush,
+ .cancel_all_reqs = svc_i3c_cancel_all_reqs,
+ .get_features = svc_i3c_get_features,
+ .hotjoin = svc_i3c_hotjoin,
+ .fifo_status = svc_i3c_fifo_status,
+ .set_status_format1 = svc_i3c_set_status_format1,
+ .get_status_format1 = svc_i3c_get_status_format1,
+ .get_addr = svc_i3c_get_addr,
+};
+
+static int svc_i3c_target_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct i3c_target_ctrl *target;
+ struct svc_i3c_target *svc;
+ int ret;
+ u32 val;
+
+ svc = devm_kzalloc(dev, sizeof(*svc), GFP_KERNEL);
+ if (!svc)
+ return -ENOMEM;
+
+ svc->regs = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(svc->regs))
+ return PTR_ERR(svc->regs);
+
+ svc->clks[PCLK].id = "pclk";
+ svc->clks[FCLK].id = "fast_clk";
+ svc->clks[SCLK].id = "slow_clk";
+
+ ret = devm_clk_bulk_get(dev, MAXCLK, svc->clks);
+ if (ret < 0) {
+ dev_err(dev, "fail get clks: %d\n", ret);
+ return ret;
+ }
+
+ ret = clk_bulk_prepare_enable(MAXCLK, svc->clks);
+ if (ret < 0) {
+ dev_err(dev, "fail enable clks: %d\n", ret);
+ return ret;
+ }
+
+ svc->irq = platform_get_irq(pdev, 0);
+ if (svc->irq < 0)
+ return svc->irq;
+
+ INIT_LIST_HEAD(&svc->txq);
+ INIT_LIST_HEAD(&svc->rxq);
+ INIT_LIST_HEAD(&svc->cq);
+ spin_lock_init(&svc->txq_lock);
+ spin_lock_init(&svc->rxq_lock);
+ spin_lock_init(&svc->cq_lock);
+ spin_lock_init(&svc->ctrl_lock);
+
+ init_completion(&svc->dacomplete);
+
+ INIT_WORK(&svc->work, svc_i3c_target_complete);
+ svc->workqueue = alloc_workqueue("%s-cq", 0, 0, dev_name(dev));
+ if (!svc->workqueue)
+ return -ENOMEM;
+
+ /* Disable all IRQ */
+ writel_relaxed(0xFFFFFFFF, svc->regs + I3C_SINTCLR);
+
+ val = readl_relaxed(svc->regs + I3C_SCAPABILITIES);
+ svc->features.tx_fifo_sz = FIELD_GET(I3C_SCAPABILITIES_FIFOTX_MASK, val);
+ svc->features.tx_fifo_sz = 2 << svc->features.tx_fifo_sz;
+
+ svc->features.rx_fifo_sz = FIELD_GET(I3C_SCAPABILITIES_FIFORX_MASK, val);
+ svc->features.rx_fifo_sz = 2 << svc->features.rx_fifo_sz;
+
+ ret = devm_request_irq(dev, svc->irq, svc_i3c_target_irq_handler, 0, "svc-i3c-irq", svc);
+ if (ret)
+ return -ENOENT;
+
+ target = devm_i3c_target_ctrl_create(dev, &svc_i3c_target_ops);
+ if (!target)
+ return -ENOMEM;
+
+ dev_set_drvdata(&target->dev, svc);
+
+ return 0;
+}
+
+static int svc_i3c_target_remove(struct platform_device *pdev)
+{
+ return 0;
+}
+
+static const struct of_device_id svc_i3c_target_of_match_tbl[] = {
+ { .compatible = "silvaco,i3c-target-v1" },
+ { /* sentinel */ },
+};
+MODULE_DEVICE_TABLE(of, svc_i3c_target_of_match_tbl);
+
+static struct platform_driver svc_i3c_target = {
+ .probe = svc_i3c_target_probe,
+ .remove = svc_i3c_target_remove,
+ .driver = {
+ .name = "silvaco-i3c-target",
+ .of_match_table = svc_i3c_target_of_match_tbl,
+ //.pm = &svc_i3c_pm_ops,
+ },
+};
+module_platform_driver(svc_i3c_target);
+
+MODULE_DESCRIPTION("Silvaco dual-role I3C target driver");
+MODULE_LICENSE("GPL");
--
2.34.1


2024-01-10 17:54:24

by Frank Li

[permalink] [raw]
Subject: [PATCH v2 5/7] i3c: target: func: add tty driver

Add tty over I3C target function driver.

Signed-off-by: Frank Li <[email protected]>
---
drivers/i3c/Kconfig | 1 +
drivers/i3c/Makefile | 1 +
drivers/i3c/func/Kconfig | 9 +
drivers/i3c/func/Makefile | 3 +
drivers/i3c/func/tty.c | 475 ++++++++++++++++++++++++++++++++++++++
5 files changed, 489 insertions(+)
create mode 100644 drivers/i3c/func/Kconfig
create mode 100644 drivers/i3c/func/Makefile
create mode 100644 drivers/i3c/func/tty.c

diff --git a/drivers/i3c/Kconfig b/drivers/i3c/Kconfig
index 08ceef313f831..e524a8777e182 100644
--- a/drivers/i3c/Kconfig
+++ b/drivers/i3c/Kconfig
@@ -50,4 +50,5 @@ config I3C_TARGET_CONFIGFS

if I3C_TARGET
source "drivers/i3c/target/Kconfig"
+source "drivers/i3c/func/Kconfig"
endif # I3C_TARGET
diff --git a/drivers/i3c/Makefile b/drivers/i3c/Makefile
index c36455cb852ea..1f7e5fa9d25c2 100644
--- a/drivers/i3c/Makefile
+++ b/drivers/i3c/Makefile
@@ -5,3 +5,4 @@ obj-$(CONFIG_I3C) += master/
obj-$(CONFIG_I3C_TARGET) += target.o
obj-$(CONFIG_I3C_TARGET_CONFIGFS) += i3c-cfs.o
obj-$(CONFIG_I3C_TARGET) += target/
+obj-$(CONFIG_I3C_TARGET) += func/
diff --git a/drivers/i3c/func/Kconfig b/drivers/i3c/func/Kconfig
new file mode 100644
index 0000000000000..6302061e02279
--- /dev/null
+++ b/drivers/i3c/func/Kconfig
@@ -0,0 +1,9 @@
+# SPDX-License-Identifier: GPL-2.0
+
+config I3C_TARGET_FUNC_TTY
+ tristate "PCI Endpoint Test driver"
+ depends on I3C_TARGET
+ help
+ I3C Target TTY Function Driver.
+
+ General TTY over I3C target controller function drivers.
diff --git a/drivers/i3c/func/Makefile b/drivers/i3c/func/Makefile
new file mode 100644
index 0000000000000..16b3b9301496b
--- /dev/null
+++ b/drivers/i3c/func/Makefile
@@ -0,0 +1,3 @@
+# SPDX-License-Identifier: GPL-2.0
+
+obj-$(CONFIG_I3C_TARGET_FUNC_TTY) += tty.o
diff --git a/drivers/i3c/func/tty.c b/drivers/i3c/func/tty.c
new file mode 100644
index 0000000000000..bad99c08be0ac
--- /dev/null
+++ b/drivers/i3c/func/tty.c
@@ -0,0 +1,475 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2023 NXP
+ * Author: Frank Li <[email protected]>
+ */
+
+#include <linux/iopoll.h>
+#include <linux/i3c/target.h>
+#include <linux/serial_core.h>
+#include <linux/slab.h>
+#include <linux/tty_flip.h>
+
+static DEFINE_IDR(i3c_tty_minors);
+
+static struct tty_driver *i3c_tty_driver;
+
+#define I3C_TTY_MINORS 8
+
+#define I3C_TX_NOEMPTY BIT(0)
+#define I3C_TTY_TRANS_SIZE 16
+#define I3C_TTY_IBI_TX BIT(0)
+
+struct ttyi3c_port {
+ struct tty_port port;
+ int minor;
+ struct i3c_target_func *i3cdev;
+ struct completion txcomplete;
+ spinlock_t xlock;
+ void *buffer;
+ struct work_struct work;
+ u16 status;
+ struct i3c_request *req;
+};
+
+static void i3c_target_tty_rx_complete(struct i3c_request *req)
+{
+ struct ttyi3c_port *port = req->context;
+
+ if (req->status == I3C_REQUEST_CANCEL) {
+ i3c_target_ctrl_free_request(req);
+ return;
+ }
+
+ tty_insert_flip_string(&port->port, req->buf, req->actual);
+ tty_flip_buffer_push(&port->port);
+
+ req->actual = 0;
+ req->status = 0;
+ i3c_target_ctrl_queue(req, GFP_KERNEL);
+}
+
+static void i3c_target_tty_tx_complete(struct i3c_request *req)
+{
+ struct ttyi3c_port *sport = req->context;
+ unsigned long flags;
+
+ if (req->status == I3C_REQUEST_CANCEL) {
+ i3c_target_ctrl_free_request(req);
+ return;
+ }
+
+ spin_lock_irqsave(&sport->xlock, flags);
+ kfifo_dma_out_finish(&sport->port.xmit_fifo, req->actual);
+ sport->req = NULL;
+
+ if (kfifo_is_empty(&sport->port.xmit_fifo))
+ complete(&sport->txcomplete);
+ else
+ queue_work(system_unbound_wq, &sport->work);
+
+ if (kfifo_len(&sport->port.xmit_fifo) < WAKEUP_CHARS)
+ tty_port_tty_wakeup(&sport->port);
+ spin_unlock_irqrestore(&sport->xlock, flags);
+
+ i3c_target_ctrl_free_request(req);
+}
+
+static void i3c_target_tty_i3c_work(struct work_struct *work)
+{
+ struct ttyi3c_port *sport = container_of(work, struct ttyi3c_port, work);
+ struct i3c_request *req = sport->req;
+ struct scatterlist sg[1];
+ unsigned int nents;
+ u8 ibi;
+
+ if (kfifo_is_empty(&sport->port.xmit_fifo))
+ return;
+
+ if (!req) {
+ req = i3c_target_ctrl_alloc_request(sport->i3cdev->ctrl, GFP_KERNEL);
+ if (!req)
+ return;
+
+ sg_init_table(sg, ARRAY_SIZE(sg));
+ nents = kfifo_dma_out_prepare(&sport->port.xmit_fifo, sg, ARRAY_SIZE(sg),
+ UART_XMIT_SIZE);
+ if (!nents)
+ goto err;
+
+ req->length = sg->length;
+ req->buf = sg_virt(sg);
+
+ req->complete = i3c_target_tty_tx_complete;
+ req->context = sport;
+ req->tx = true;
+
+ if (i3c_target_ctrl_queue(req, GFP_KERNEL))
+ goto err;
+
+ sport->req = req;
+ }
+
+ ibi = I3C_TTY_IBI_TX;
+ i3c_target_ctrl_raise_ibi(sport->i3cdev->ctrl, &ibi, 1);
+
+ return;
+
+err:
+ i3c_target_ctrl_free_request(req);
+}
+
+static int i3c_port_activate(struct tty_port *port, struct tty_struct *tty)
+{
+ struct ttyi3c_port *sport = container_of(port, struct ttyi3c_port, port);
+ const struct i3c_target_ctrl_features *feature;
+ struct i3c_target_func *func = sport->i3cdev;
+ struct i3c_request *req;
+ int rxfifo_size;
+ int offset = 0;
+ int ret;
+
+ feature = i3c_target_ctrl_get_features(func->ctrl);
+ if (!feature)
+ return -EINVAL;
+
+ ret = tty_port_alloc_xmit_buf(port);
+ if (ret)
+ return ret;
+
+ sport->buffer = (void *)get_zeroed_page(GFP_KERNEL);
+ if (!sport->buffer)
+ goto err_alloc_rx_buf;
+
+ rxfifo_size = feature->rx_fifo_sz;
+
+ if (!rxfifo_size)
+ rxfifo_size = I3C_TTY_TRANS_SIZE;
+
+ do {
+ req = i3c_target_ctrl_alloc_request(func->ctrl, GFP_KERNEL);
+ if (!req)
+ goto err_alloc_req;
+
+ req->buf = (void *) (sport->buffer + offset);
+ req->length = rxfifo_size;
+ req->context = sport;
+ req->complete = i3c_target_tty_rx_complete;
+ offset += rxfifo_size;
+
+ if (i3c_target_ctrl_queue(req, GFP_KERNEL))
+ goto err_alloc_req;
+ } while (req && (offset + rxfifo_size) < UART_XMIT_SIZE);
+
+ reinit_completion(&sport->txcomplete);
+
+ return 0;
+
+err_alloc_req:
+ i3c_target_ctrl_cancel_all_reqs(func->ctrl, false);
+ free_page((unsigned long)sport->buffer);
+err_alloc_rx_buf:
+ tty_port_free_xmit_buf(port);
+ return -ENOMEM;
+}
+
+static void i3c_port_shutdown(struct tty_port *port)
+{
+ struct ttyi3c_port *sport =
+ container_of(port, struct ttyi3c_port, port);
+
+ cancel_work_sync(&sport->work);
+
+ i3c_target_ctrl_cancel_all_reqs(sport->i3cdev->ctrl, true);
+ i3c_target_ctrl_cancel_all_reqs(sport->i3cdev->ctrl, false);
+
+ i3c_target_ctrl_fifo_flush(sport->i3cdev->ctrl, true);
+ i3c_target_ctrl_fifo_flush(sport->i3cdev->ctrl, false);
+
+ tty_port_free_xmit_buf(port);
+ free_page((unsigned long)sport->buffer);
+}
+
+static void i3c_port_destruct(struct tty_port *port)
+{
+ struct ttyi3c_port *sport =
+ container_of(port, struct ttyi3c_port, port);
+
+ idr_remove(&i3c_tty_minors, sport->minor);
+}
+
+static const struct tty_port_operations i3c_port_ops = {
+ .shutdown = i3c_port_shutdown,
+ .activate = i3c_port_activate,
+ .destruct = i3c_port_destruct,
+};
+
+static int i3c_target_tty_bind(struct i3c_target_func *func)
+{
+ struct ttyi3c_port *sport;
+ struct device *tty_dev;
+ int minor;
+ int ret;
+
+ sport = dev_get_drvdata(&func->dev);
+
+ if (i3c_target_ctrl_set_config(func->ctrl, func)) {
+ dev_err(&func->dev, "failure set i3c config\n");
+ return -EINVAL;
+ }
+
+ spin_lock_init(&sport->xlock);
+ init_completion(&sport->txcomplete);
+
+ ret = minor = idr_alloc(&i3c_tty_minors, sport, 0, I3C_TTY_MINORS, GFP_KERNEL);
+
+ if (minor < 0)
+ goto err_idr_alloc;
+
+ tty_port_init(&sport->port);
+ sport->port.ops = &i3c_port_ops;
+
+ tty_dev = tty_port_register_device(&sport->port, i3c_tty_driver, minor,
+ &func->dev);
+ if (IS_ERR(tty_dev)) {
+ ret = PTR_ERR(tty_dev);
+ goto err_register_port;
+ }
+
+ sport->minor = minor;
+ ret = i3c_target_ctrl_enable(func->ctrl);
+ if (ret)
+ goto err_ctrl_enable;
+
+ return 0;
+
+err_ctrl_enable:
+ tty_port_unregister_device(&sport->port, i3c_tty_driver, sport->minor);
+err_register_port:
+ idr_remove(&i3c_tty_minors, sport->minor);
+err_idr_alloc:
+ i3c_target_ctrl_cancel_all_reqs(func->ctrl, false);
+ dev_err(&func->dev, "bind failure\n");
+
+ return ret;
+}
+
+static void i3c_target_tty_unbind(struct i3c_target_func *func)
+{
+ struct ttyi3c_port *sport;
+
+ sport = dev_get_drvdata(&func->dev);
+
+ cancel_work_sync(&sport->work);
+
+ i3c_target_ctrl_disable(func->ctrl);
+ i3c_target_ctrl_cancel_all_reqs(func->ctrl, 0);
+ i3c_target_ctrl_cancel_all_reqs(func->ctrl, 1);
+
+ tty_port_unregister_device(&sport->port, i3c_tty_driver, sport->minor);
+
+ free_page((unsigned long)sport->buffer);
+}
+
+static struct i3c_target_func_ops i3c_func_ops = {
+ .bind = i3c_target_tty_bind,
+ .unbind = i3c_target_tty_unbind,
+};
+
+static int i3c_tty_probe(struct i3c_target_func *func)
+{
+ struct device *dev = &func->dev;
+ struct ttyi3c_port *port;
+
+ port = devm_kzalloc(dev, sizeof(*port), GFP_KERNEL);
+ if (!port)
+ return -ENOMEM;
+
+ port->i3cdev = func;
+ dev_set_drvdata(&func->dev, port);
+
+ INIT_WORK(&port->work, i3c_target_tty_i3c_work);
+
+ return 0;
+}
+
+static ssize_t i3c_write(struct tty_struct *tty, const unsigned char *buf, size_t count)
+{
+ struct ttyi3c_port *sport = tty->driver_data;
+ unsigned long flags;
+ bool is_empty;
+ int ret = 0;
+
+ spin_lock_irqsave(&sport->xlock, flags);
+ ret = kfifo_in(&sport->port.xmit_fifo, buf, count);
+ is_empty = kfifo_is_empty(&sport->port.xmit_fifo);
+ i3c_target_ctrl_set_status_format1(sport->i3cdev->ctrl, sport->status | I3C_TX_NOEMPTY);
+ spin_unlock_irqrestore(&sport->xlock, flags);
+
+ if (!is_empty)
+ queue_work(system_unbound_wq, &sport->work);
+
+ return ret;
+}
+
+static int i3c_put_char(struct tty_struct *tty, unsigned char ch)
+{
+ struct ttyi3c_port *sport = tty->driver_data;
+ unsigned long flags;
+ int ret = 0;
+
+ spin_lock_irqsave(&sport->xlock, flags);
+ ret = kfifo_put(&sport->port.xmit_fifo, ch);
+ spin_unlock_irqrestore(&sport->xlock, flags);
+
+ return ret;
+}
+
+static void i3c_flush_chars(struct tty_struct *tty)
+{
+ struct ttyi3c_port *sport = tty->driver_data;
+ unsigned long flags;
+
+ spin_lock_irqsave(&sport->xlock, flags);
+ if (!kfifo_is_empty(&sport->port.xmit_fifo))
+ queue_work(system_unbound_wq, &sport->work);
+ spin_unlock_irqrestore(&sport->xlock, flags);
+}
+
+static unsigned int i3c_write_room(struct tty_struct *tty)
+{
+ struct ttyi3c_port *sport = tty->driver_data;
+
+ return kfifo_avail(&sport->port.xmit_fifo);
+}
+
+static void i3c_throttle(struct tty_struct *tty)
+{
+ struct ttyi3c_port *sport = tty->driver_data;
+
+ i3c_target_ctrl_cancel_all_reqs(sport->i3cdev->ctrl, false);
+}
+
+static void i3c_unthrottle(struct tty_struct *tty)
+{
+ struct ttyi3c_port *sport = tty->driver_data;
+
+ i3c_port_activate(&sport->port, tty);
+}
+
+static int i3c_open(struct tty_struct *tty, struct file *filp)
+{
+ struct ttyi3c_port *sport = container_of(tty->port, struct ttyi3c_port, port);
+ int ret;
+
+ tty->driver_data = sport;
+
+ if (!i3c_target_ctrl_get_addr(sport->i3cdev->ctrl)) {
+ dev_dbg(&sport->i3cdev->dev, "No target addr assigned, try hotjoin");
+ ret = i3c_target_ctrl_hotjoin(sport->i3cdev->ctrl);
+ if (ret) {
+ dev_err(&sport->i3cdev->dev, "Hotjoin failure, check connection");
+ return ret;
+ }
+ }
+
+ return tty_port_open(&sport->port, tty, filp);
+}
+
+static void i3c_close(struct tty_struct *tty, struct file *filp)
+{
+ tty_port_close(tty->port, tty, filp);
+}
+
+static void i3c_wait_until_sent(struct tty_struct *tty, int timeout)
+{
+ struct ttyi3c_port *sport = tty->driver_data;
+ int val;
+ int ret;
+ u8 ibi = I3C_TTY_IBI_TX;
+ int retry = 100;
+
+ if (!kfifo_is_empty(&sport->port.xmit_fifo)) {
+ do {
+ ret = wait_for_completion_timeout(&sport->txcomplete, timeout / 100);
+ if (ret)
+ break;
+ i3c_target_ctrl_raise_ibi(sport->i3cdev->ctrl, &ibi, 1);
+ } while (retry--);
+
+ reinit_completion(&sport->txcomplete);
+ }
+
+ read_poll_timeout(i3c_target_ctrl_fifo_status, val, !val, 100, timeout, false,
+ sport->i3cdev->ctrl, true);
+
+ i3c_target_ctrl_set_status_format1(sport->i3cdev->ctrl, sport->status & (~I3C_TX_NOEMPTY));
+}
+
+static const struct tty_operations i3c_tty_ops = {
+ .open = i3c_open,
+ .close = i3c_close,
+ .write = i3c_write,
+ .put_char = i3c_put_char,
+ .flush_chars = i3c_flush_chars,
+ .write_room = i3c_write_room,
+ .throttle = i3c_throttle,
+ .unthrottle = i3c_unthrottle,
+ .wait_until_sent = i3c_wait_until_sent,
+};
+
+DECLARE_I3C_TARGET_FUNC(tty, i3c_tty_probe, NULL, &i3c_func_ops);
+
+static int __init i3c_tty_init(void)
+{
+ int ret;
+
+ i3c_tty_driver = tty_alloc_driver(
+ I3C_TTY_MINORS, TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV);
+
+ if (IS_ERR(i3c_tty_driver))
+ return PTR_ERR(i3c_tty_driver);
+
+ i3c_tty_driver->driver_name = "ttySI3C", i3c_tty_driver->name = "ttySI3C",
+ i3c_tty_driver->minor_start = 0,
+ i3c_tty_driver->type = TTY_DRIVER_TYPE_SERIAL,
+ i3c_tty_driver->subtype = SERIAL_TYPE_NORMAL,
+ i3c_tty_driver->init_termios = tty_std_termios;
+ i3c_tty_driver->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL |
+ CLOCAL;
+ i3c_tty_driver->init_termios.c_lflag = 0;
+
+ tty_set_operations(i3c_tty_driver, &i3c_tty_ops);
+
+ ret = tty_register_driver(i3c_tty_driver);
+ if (ret)
+ goto err_register_tty_driver;
+
+ ret = i3c_target_func_register_driver(&ttyi3c_func);
+ if (ret)
+ goto err_register_i3c_driver;
+
+ return 0;
+
+err_register_i3c_driver:
+ tty_unregister_driver(i3c_tty_driver);
+
+err_register_tty_driver:
+ tty_driver_kref_put(i3c_tty_driver);
+
+ return ret;
+}
+
+static void __exit i3c_tty_exit(void)
+{
+ i3c_target_func_unregister_driver(&ttyi3c_func);
+ tty_unregister_driver(i3c_tty_driver);
+ tty_driver_kref_put(i3c_tty_driver);
+ idr_destroy(&i3c_tty_minors);
+}
+
+module_init(i3c_tty_init);
+module_exit(i3c_tty_exit);
+
+MODULE_LICENSE("GPL");
+
--
2.34.1


2024-01-10 17:56:39

by Frank Li

[permalink] [raw]
Subject: [PATCH v2 3/7] Documentation: i3c: Add I3C target mode controller and function

Add I3C target mode and tty over i3c func driver document.

Signed-off-by: Frank Li <[email protected]>
---
Documentation/driver-api/i3c/index.rst | 1 +
.../driver-api/i3c/target/i3c-target-cfs.rst | 109 ++++++++++
.../driver-api/i3c/target/i3c-target.rst | 189 ++++++++++++++++++
.../driver-api/i3c/target/i3c-tty-howto.rst | 109 ++++++++++
Documentation/driver-api/i3c/target/index.rst | 13 ++
5 files changed, 421 insertions(+)
create mode 100644 Documentation/driver-api/i3c/target/i3c-target-cfs.rst
create mode 100644 Documentation/driver-api/i3c/target/i3c-target.rst
create mode 100644 Documentation/driver-api/i3c/target/i3c-tty-howto.rst
create mode 100644 Documentation/driver-api/i3c/target/index.rst

diff --git a/Documentation/driver-api/i3c/index.rst b/Documentation/driver-api/i3c/index.rst
index 783d6dad054b6..345a43c9f61b0 100644
--- a/Documentation/driver-api/i3c/index.rst
+++ b/Documentation/driver-api/i3c/index.rst
@@ -9,3 +9,4 @@ I3C subsystem
protocol
device-driver-api
master-driver-api
+ target/index
diff --git a/Documentation/driver-api/i3c/target/i3c-target-cfs.rst b/Documentation/driver-api/i3c/target/i3c-target-cfs.rst
new file mode 100644
index 0000000000000..1fcf829dc4ae2
--- /dev/null
+++ b/Documentation/driver-api/i3c/target/i3c-target-cfs.rst
@@ -0,0 +1,109 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+=======================================
+Configuring I3C Target Using CONFIGFS
+=======================================
+
+:Author: Frank Li <[email protected]>
+
+The I3C Target Core exposes configfs entry (i3c_target) to configure the I3C
+target function and to bind the target function with the target controller.
+(For introducing other mechanisms to configure the I3C Target Function refer to
+[1]).
+
+Mounting configfs
+=================
+
+The I3C Target Core layer creates i3c_target directory in the mounted configfs
+directory. configfs can be mounted using the following command::
+
+ mount -t configfs none /sys/kernel/config
+
+Directory Structure
+===================
+
+The i3c_target configfs has two directories at its root: controllers and
+functions. Every Controller device present in the system will have an entry in
+the *controllers* directory and every Function driver present in the system will
+have an entry in the *functions* directory.
+::
+
+ /sys/kernel/config/i3c_target/
+ .. controllers/
+ .. functions/
+
+Creating Function Device
+===================
+
+Every registered Function driver will be listed in controllers directory. The
+entries corresponding to Function driver will be created by the Function core.
+::
+
+ /sys/kernel/config/i3c_target/functions/
+ .. <Function Driver1>/
+ ... <Function Device 11>/
+ ... <Function Device 21>/
+ ... <Function Device 31>/
+ .. <Function Driver2>/
+ ... <Function Device 12>/
+ ... <Function Device 22>/
+
+In order to create a <Function device> of the type probed by <Function Driver>,
+the user has to create a directory inside <Function DriverN>.
+
+Every <Function device> directory consists of the following entries that can be
+used to configure the standard configuration header of the target function.
+(These entries are created by the framework when any new <Function Device> is
+created)
+::
+
+ .. <Function Driver1>/
+ ... <Function Device 11>/
+ ... vendor_id
+ ... part_id
+ ... bcr
+ ... dcr
+ ... ext_id
+ ... instance_id
+ ... max_read_len
+ ... max_write_len
+ ... vendor_info
+
+Controller Device
+==========
+
+Every registered Controller device will be listed in controllers directory. The
+entries corresponding to Controller device will be created by the Controller
+core.
+::
+
+ /sys/kernel/config/i3c_target/controllers/
+ .. <Controller Device1>/
+ ... <Symlink Function Device11>/
+ .. <Controller Device2>/
+ ... <Symlink Function Device21>/
+
+The <Controller Device> directory will have a list of symbolic links to
+<Function Device>. These symbolic links should be created by the user to
+represent the functions present in the target device. Only <Function Device>
+that represents a physical function can be linked to a Controller device.
+
+::
+
+ | controllers/
+ | <Directory: Controller name>/
+ | <Symbolic Link: Function>
+ | functions/
+ | <Directory: Function driver>/
+ | <Directory: Function device>/
+ | vendor_id
+ | part_id
+ | bcr
+ | dcr
+ | ext_id
+ | instance_id
+ | max_read_len
+ | max_write_len
+ | vendor_info
+
+[1] Documentation/I3C/target/pci-target.rst
diff --git a/Documentation/driver-api/i3c/target/i3c-target.rst b/Documentation/driver-api/i3c/target/i3c-target.rst
new file mode 100644
index 0000000000000..09ae26b1f311a
--- /dev/null
+++ b/Documentation/driver-api/i3c/target/i3c-target.rst
@@ -0,0 +1,189 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+:Author: Frank Li <[email protected]>
+
+This document is a guide to use the I3C Target Framework in order to create
+target controller driver, target function driver, and using configfs interface
+to bind the function driver to the controller driver.
+
+Introduction
+============
+
+Linux has a comprehensive I3C subsystem to support I3C controllers that
+operates in master mode. The subsystem has capability to scan I3C bus,assign
+i3c device address, load I3C driver (based on Manufacturer ID, part ID),
+support other services like hot-join, In-Band Interrupt(IBI).
+
+However the I3C controller IP integrated in some SoCs is capable of operating
+either in Master mode or Target mode. I3C Target Framework will add target mode
+support in Linux. This will help to run Linux in an target system which can
+have a wide variety of use cases from testing or validation, co-processor
+accelerator, etc.
+
+I3C Target Core
+=================
+
+The I3C Target Core layer comprises 3 components: the Target Controller
+library, the Target Function library, and the configfs layer to bind the target
+function with the target controller.
+
+I3C Target Controller Library
+------------------------------------
+
+The Controller library provides APIs to be used by the controller that can
+operate in target mode. It also provides APIs to be used by function
+driver/library in order to implement a particular target function.
+
+APIs for the I3C Target controller Driver
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+This section lists the APIs that the I3C Target core provides to be used by the
+I3C controller driver.
+
+* devm_i3c_target_ctrl_create()/i3c_target_ctrl_create()
+
+ The I3C controller driver should implement the following ops:
+
+ * set_config: ops to set i3c configuration
+ * enable: ops to enable controller
+ * disable: ops to disable controller
+ * raise_ibi: ops to raise IBI to master controller
+ * alloc_request: ops to alloc a transfer request
+ * free_request: ops to free a transfer request
+ * queue: ops to queue a request to transfer queue
+ * dequeue: ops to dequeue a request from transfer queue
+ * cancel_all_reqs: ops to cancel all request from transfer queue
+ * fifo_status: ops to get fifo status
+ * fifo_flush: ops to flush hardware fifo
+ * get_features: ops to get controller supported features
+
+ The I3C controller driver can then create a new Controller device by
+ invoking devm_i3c_target_ctrl_create()/i3c_target_ctrl_create().
+
+* devm_i3c_target_ctrl_destroy()/i3c_target_ctrl_destroy()
+
+ The I3C controller driver can destroy the Controller device created by
+ either devm_i3c_target_ctrl_create() or i3c_target_ctrl_create() using
+ devm_i3c_target_ctrl_destroy() or i3c_target_ctrl_destroy().
+
+I3C Target Controller APIs for the I3C Target Function Driver
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+This section lists the APIs that the I3C Target core provides to be used by the
+I3C target function driver.
+
+* i3c_target_ctrl_set_config()
+
+ The I3C target function driver should use i3c_target_ctrl_set_config() to
+ write i3c configuration to the target controller.
+
+* i3c_target_ctrl_enable()/i3c_target_ctrl_disable()
+
+ The I3C target function driver should use i3c_target_ctrl_enable()/
+ i3c_target_ctrl_disable() to enable/disable i3c target controller.
+
+* i3c_target_ctrl_alloc_request()/i3c_target_ctrl_free_request()
+
+ The I3C target function driver should usei3c_target_ctrl_alloc_request() /
+ i3c_target_ctrl_free_request() to alloc/free a i3c request.
+
+* i3c_target_ctrl_raise_ibi()
+
+ The I3C target function driver should use i3c_target_ctrl_raise_ibi() to
+ raise IBI.
+
+* i3c_target_ctrl_queue()/i3c_target_ctrl_dequeue()
+
+ The I3C target function driver should use i3c_target_ctrl_queue()/
+ i3c_target_ctrl_dequeue(), to queue/dequeue I3C transfer to/from transfer
+ queue.
+
+* i3c_target_ctrl_get_features()
+
+ The I3C target function driver should use i3c_target_ctrl_get_features() to
+ get I3C target controller supported features.
+
+Other I3C Target Controller APIs
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+There are other APIs provided by the Controller library. These are used for
+binding the I3C Target Function device with Controlller device. i3c-cfs.c can
+be used as reference for using these APIs.
+
+* i3c_target_ctrl_get()
+
+ Get a reference to the I3C target controller based on the device name of
+ the controller.
+
+* i3c_target_ctrl_put()
+
+ Release the reference to the I3C target controller obtained using
+ i3c_target_ctrl_get()
+
+* i3c_target_ctrl_add_func()
+
+ Add a I3C target function to a I3C target controller.
+
+* i3c_target_ctrl_remove_func()
+
+ Remove the I3C target function from I3C target controller.
+
+I3C Target Function Library
+----------------------------------
+
+The I3C Target Function library provides APIs to be used by the function driver
+and the Controller library to provide target mode functionality.
+
+I3C Target Function APIs for the I3C Target Function Driver
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+This section lists the APIs that the I3C Target core provides to be used
+by the I3C target function driver.
+
+* i3c_target_func_register_driver()
+
+ The I3C Target Function driver should implement the following ops:
+ * bind: ops to perform when a Controller device has been bound to
+ Function device
+ * unbind: ops to perform when a binding has been lost between a
+ Controller device and Function device
+
+ The I3C Function driver can then register the I3C Function driver by using
+ i3c_target_func_register_driver().
+
+* i3c_target_func_unregister_driver()
+
+ The I3C Function driver can unregister the I3C Function driver by using
+ i3c_epf_unregister_driver().
+
+APIs for the I3C Target Controller Library
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+This section lists the APIs that the I3C Target core provides to be used by the
+I3C target controller library.
+
+Other I3C Target APIs
+~~~~~~~~~~~~~~~~~~~~
+
+There are other APIs provided by the Function library. These are used to notify
+the function driver when the Function device is bound to the EPC device.
+i3c-cfs.c can be used as reference for using these APIs.
+
+* i3c_target_func_create()
+
+ Create a new I3C Function device by passing the name of the I3C EPF device.
+ This name will be used to bind the Function device to a Function driver.
+
+* i3c_target_func_destroy()
+
+ Destroy the created I3C Function device.
+
+* i3c_target_func_bind()
+
+ i3c_target_func_bind() should be invoked when the EPF device has been bound
+ to a Controller device.
+
+* i3c_target_func_unbind()
+
+ i3c_target_func_unbind() should be invoked when the binding between EPC
+ device and function device is lost.
diff --git a/Documentation/driver-api/i3c/target/i3c-tty-howto.rst b/Documentation/driver-api/i3c/target/i3c-tty-howto.rst
new file mode 100644
index 0000000000000..43a129b18e938
--- /dev/null
+++ b/Documentation/driver-api/i3c/target/i3c-tty-howto.rst
@@ -0,0 +1,109 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+===================
+I3C TTY User Guide
+===================
+
+:Author: Frank Li <[email protected]>
+
+This document is a guide to help users use i3c-target-tty function driver and
+i3ctty master driver for testing I3C. The list of steps to be followed in the
+master side and target side is given below.
+
+Endpoint Device
+===============
+
+Endpoint Controller Devices
+---------------------------
+
+To find the list of target controller devices in the system::
+
+ # ls /sys/class/i3c_target/
+ 44330000.i3c-target
+
+If CONFIG_I3C_SLAVE_CONFIGFS is enabled::
+
+ # ls /sys/kernel/config/i3c_target/controllers/
+ 44330000.i3c-target
+
+
+Endpoint Function Drivers
+-------------------------
+
+To find the list of target function drivers in the system::
+
+ # ls /sys/bus/i3c_target_func/drivers
+ tty
+
+If CONFIG_I3C_SLAVE_CONFIGFS is enabled::
+
+ # ls /sys/kernel/config/i3c_target/functions
+ tty
+
+
+Creating i3c-target-tty Device
+----------------------------
+
+I3C target function device can be created using the configfs. To create
+i3c-target-tty device, the following commands can be used::
+
+ # mount -t configfs none /sys/kernel/config
+ # cd /sys/kernel/config/i3c_target/
+ # mkdir functions/tty/func1
+
+The "mkdir func1" above creates the i3c-target-tty function device that will
+be probed by i3c tty driver.
+
+The I3C target framework populates the directory with the following
+configurable fields::
+
+ # ls functions/tty/func1
+ bcr dcr ext_id instance_id max_read_len max_write_len
+ part_id vendor_id vendor_info
+
+The I3C target function driver populates these entries with default values when
+the device is bound to the driver. The i3c-target-tty driver populates vendorid
+with 0xffff and interrupt_pin with 0x0001::
+
+ # cat functions/tty/func1/vendor_id
+ 0x0
+
+Configuring i3c-target-tty Device
+-------------------------------
+
+The user can configure the i3c-target-tty device using configfs entry. In order
+to change the vendorid, the following commands can be used::
+
+ # echo 0x011b > functions/tty/func1/vendor_id
+ # echo 0x1000 > functions/tty/func1/part_id
+ # echo 0x6 > functions/tty/t/bcr
+
+Binding i3c-target-tty Device to target Controller
+------------------------------------------------
+
+In order for the target function device to be useful, it has to be bound to a
+I3C target controller driver. Use the configfs to bind the function device to
+one of the controller driver present in the system::
+
+ # ln -s functions/tty/func1 controllers/44330000.i3c-target/
+
+I3C Master Device
+================
+
+Check I3C tty device is probed
+
+ # ls /sys/bus/i3c/devices/0-23610000000
+ 0-23610000000:0 bcr dcr driver dynamic_address hdrcap
+ modalias pid power subsystem tty uevent
+
+Using Target TTY function Device
+-----------------------------------
+
+Host side:
+ cat /dev/ttyI3C0
+Target side
+ echo abc >/dev/ttyI3C0
+
+You will see "abc" show at console.
+
+You can use other tty tool to test I3C target tty device.
diff --git a/Documentation/driver-api/i3c/target/index.rst b/Documentation/driver-api/i3c/target/index.rst
new file mode 100644
index 0000000000000..56eabfae83aa4
--- /dev/null
+++ b/Documentation/driver-api/i3c/target/index.rst
@@ -0,0 +1,13 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+======================
+I3C Target Framework
+======================
+
+.. toctree::
+ :maxdepth: 2
+
+ i3c-target
+ i3c-target-cfs
+ i3c-tty-howto
+
--
2.34.1


2024-01-10 17:59:14

by Frank Li

[permalink] [raw]
Subject: [PATCH v2 7/7] tty: i3c: add TTY over I3C master support

In typical embedded Linux systems, UART consoles require at least two pins,
TX and RX. In scenarios where I2C/I3C devices like sensors or PMICs are
present, we can save these two pins by using this driver. Pins is crucial
resources, especially in small chip packages.

This introduces support for using the I3C bus to transfer console tty data,
effectively replacing the need for dedicated UART pins. This not only
conserves valuable pin resources but also facilitates testing of I3C's
advanced features, including early termination, in-band interrupt (IBI)
support, and the creation of more complex data patterns. Additionally,
it aids in identifying and addressing issues within the I3C controller
driver.

Signed-off-by: Frank Li <[email protected]>
---

Notes:
Version number use i3c target patches.
Change v2
- using system_unbound_wq working queue
- fixed accoring to Jiri Slaby's comments

Change before send with i3c target support

Change from v4 to v5
- send in i3c improvememtn patches.

Change from v2 to v4
- none

Change from v1 to v2
- update commit message.
- using goto for err handle
- using one working queue for all tty-i3c device
- fixed typo found by js
- update kconfig help
- using kfifo

Still below items not be fixed (according to Jiri Slaby's comments)
- rxwork thread: need trigger from two position.
- common thread queue: need some suggestion

drivers/tty/Kconfig | 13 ++
drivers/tty/Makefile | 1 +
drivers/tty/i3c_tty.c | 426 ++++++++++++++++++++++++++++++++++++++++++
3 files changed, 440 insertions(+)
create mode 100644 drivers/tty/i3c_tty.c

diff --git a/drivers/tty/Kconfig b/drivers/tty/Kconfig
index 5646dc6242cd9..9ab4cd480e9f8 100644
--- a/drivers/tty/Kconfig
+++ b/drivers/tty/Kconfig
@@ -412,6 +412,19 @@ config RPMSG_TTY
To compile this driver as a module, choose M here: the module will be
called rpmsg_tty.

+config I3C_TTY
+ tristate "TTY over I3C"
+ depends on I3C
+ help
+ Select this option to use TTY over I3C master controller.
+
+ This makes it possible for user-space programs to send and receive
+ data as a standard tty protocol. I3C provide relatively higher data
+ transfer rate and less pin numbers, SDA/SCL are shared with other
+ devices.
+
+ If unsure, say N
+
endif # TTY

source "drivers/tty/serdev/Kconfig"
diff --git a/drivers/tty/Makefile b/drivers/tty/Makefile
index 07aca5184a55d..f329f9c7d308a 100644
--- a/drivers/tty/Makefile
+++ b/drivers/tty/Makefile
@@ -27,5 +27,6 @@ obj-$(CONFIG_GOLDFISH_TTY) += goldfish.o
obj-$(CONFIG_MIPS_EJTAG_FDC_TTY) += mips_ejtag_fdc.o
obj-$(CONFIG_VCC) += vcc.o
obj-$(CONFIG_RPMSG_TTY) += rpmsg_tty.o
+obj-$(CONFIG_I3C_TTY) += i3c_tty.o

obj-y += ipwireless/
diff --git a/drivers/tty/i3c_tty.c b/drivers/tty/i3c_tty.c
new file mode 100644
index 0000000000000..e1e2a64b21863
--- /dev/null
+++ b/drivers/tty/i3c_tty.c
@@ -0,0 +1,426 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright 2023 NXP.
+ *
+ * Author: Frank Li <[email protected]>
+ */
+
+#include <linux/delay.h>
+#include <linux/kernel.h>
+#include <linux/mod_devicetable.h>
+#include <linux/module.h>
+#include <linux/i3c/device.h>
+#include <linux/i3c/master.h>
+#include <linux/slab.h>
+#include <linux/console.h>
+#include <linux/serial_core.h>
+#include <linux/interrupt.h>
+#include <linux/workqueue.h>
+#include <linux/tty_flip.h>
+
+static DEFINE_IDR(i3c_tty_minors);
+static DEFINE_MUTEX(i3c_tty_minors_lock);
+
+static struct tty_driver *i3c_tty_driver;
+
+#define I3C_TTY_MINORS 8
+#define I3C_TTY_TRANS_SIZE 16
+#define I3C_TTY_RX_STOP 0
+#define I3C_TTY_RETRY 20
+#define I3C_TTY_YIELD_US 100
+
+struct ttyi3c_port {
+ struct tty_port port;
+ int minor;
+ spinlock_t xlock; /* protect xmit */
+ u8 tx_buff[I3C_TTY_TRANS_SIZE];
+ u8 rx_buff[I3C_TTY_TRANS_SIZE];
+ struct i3c_device *i3cdev;
+ struct work_struct txwork;
+ struct work_struct rxwork;
+ struct completion txcomplete;
+ unsigned long status;
+ u32 buf_overrun;
+};
+
+static const struct i3c_device_id i3c_ids[] = {
+ I3C_DEVICE(0x011B, 0x1000, NULL),
+ { /* sentinel */ },
+};
+
+static int i3c_port_activate(struct tty_port *port, struct tty_struct *tty)
+{
+ struct ttyi3c_port *sport = container_of(port, struct ttyi3c_port, port);
+ int ret;
+
+ ret = tty_port_alloc_xmit_buf(port);
+ if (ret < 0)
+ return ret;
+
+ sport->status = 0;
+
+ ret = i3c_device_enable_ibi(sport->i3cdev);
+ if (ret) {
+ tty_port_free_xmit_buf(port);
+ return ret;
+ }
+
+ return 0;
+}
+
+static void i3c_port_shutdown(struct tty_port *port)
+{
+ struct ttyi3c_port *sport =
+ container_of(port, struct ttyi3c_port, port);
+
+ i3c_device_disable_ibi(sport->i3cdev);
+ tty_port_free_xmit_buf(port);
+}
+
+static void i3c_port_destruct(struct tty_port *port)
+{
+ struct ttyi3c_port *sport =
+ container_of(port, struct ttyi3c_port, port);
+
+ mutex_lock(&i3c_tty_minors_lock);
+ idr_remove(&i3c_tty_minors, sport->minor);
+ mutex_unlock(&i3c_tty_minors_lock);
+}
+
+static const struct tty_port_operations i3c_port_ops = {
+ .shutdown = i3c_port_shutdown,
+ .activate = i3c_port_activate,
+ .destruct = i3c_port_destruct,
+};
+
+static ssize_t i3c_write(struct tty_struct *tty, const unsigned char *buf, size_t count)
+{
+ struct ttyi3c_port *sport = tty->driver_data;
+ unsigned long flags;
+ bool is_empty;
+ int ret;
+
+ spin_lock_irqsave(&sport->xlock, flags);
+ ret = kfifo_in(&sport->port.xmit_fifo, buf, count);
+ is_empty = kfifo_is_empty(&sport->port.xmit_fifo);
+ spin_unlock_irqrestore(&sport->xlock, flags);
+
+ if (!is_empty)
+ queue_work(system_unbound_wq, &sport->txwork);
+
+ return ret;
+}
+
+static int i3c_put_char(struct tty_struct *tty, unsigned char ch)
+{
+ struct ttyi3c_port *sport = tty->driver_data;
+ unsigned long flags;
+ int ret;
+
+ spin_lock_irqsave(&sport->xlock, flags);
+ ret = kfifo_put(&sport->port.xmit_fifo, ch);
+ spin_unlock_irqrestore(&sport->xlock, flags);
+
+ return ret;
+}
+
+static void i3c_flush_chars(struct tty_struct *tty)
+{
+ struct ttyi3c_port *sport = tty->driver_data;
+
+ queue_work(system_unbound_wq, &sport->txwork);
+}
+
+static unsigned int i3c_write_room(struct tty_struct *tty)
+{
+ struct ttyi3c_port *sport = tty->driver_data;
+
+ return kfifo_avail(&sport->port.xmit_fifo);
+}
+
+static void i3c_throttle(struct tty_struct *tty)
+{
+ struct ttyi3c_port *sport = tty->driver_data;
+
+ clear_bit(I3C_TTY_RX_STOP, &sport->status);
+}
+
+static void i3c_unthrottle(struct tty_struct *tty)
+{
+ struct ttyi3c_port *sport = tty->driver_data;
+
+ set_bit(I3C_TTY_RX_STOP, &sport->status);
+
+ queue_work(system_unbound_wq, &sport->rxwork);
+}
+
+static int i3c_open(struct tty_struct *tty, struct file *filp)
+{
+ struct ttyi3c_port *sport = container_of(tty->port, struct ttyi3c_port, port);
+
+ tty->driver_data = sport;
+
+ return tty_port_open(&sport->port, tty, filp);
+}
+
+static void i3c_close(struct tty_struct *tty, struct file *filp)
+{
+ tty_port_close(tty->port, tty, filp);
+}
+
+static const struct tty_operations i3c_tty_ops = {
+ .open = i3c_open,
+ .close = i3c_close,
+ .write = i3c_write,
+ .put_char = i3c_put_char,
+ .flush_chars = i3c_flush_chars,
+ .write_room = i3c_write_room,
+ .throttle = i3c_throttle,
+ .unthrottle = i3c_unthrottle,
+};
+
+static void i3c_controller_irq_handler(struct i3c_device *dev,
+ const struct i3c_ibi_payload *payload)
+{
+ struct ttyi3c_port *sport = dev_get_drvdata(&dev->dev);
+
+ /* i3c_unthrottle also queue the work to fetch pending data in target side */
+ queue_work(system_unbound_wq, &sport->rxwork);
+}
+
+static void tty_i3c_rxwork(struct work_struct *work)
+{
+ struct ttyi3c_port *sport = container_of(work, struct ttyi3c_port, rxwork);
+ struct i3c_priv_xfer xfers;
+ u32 retry = I3C_TTY_RETRY;
+ u16 status = BIT(0);
+ int ret;
+
+ memset(&xfers, 0, sizeof(xfers));
+ xfers.data.in = sport->rx_buff;
+ xfers.len = I3C_TTY_TRANS_SIZE;
+ xfers.rnw = 1;
+
+ do {
+ if (test_bit(I3C_TTY_RX_STOP, &sport->status))
+ break;
+
+ i3c_device_do_priv_xfers(sport->i3cdev, &xfers, 1);
+
+ if (xfers.actual_len) {
+ ret = tty_insert_flip_string(&sport->port, sport->rx_buff,
+ xfers.actual_len);
+ if (ret < xfers.actual_len)
+ sport->buf_overrun++;
+
+ retry = I3C_TTY_RETRY;
+ continue;
+ }
+
+ status = BIT(0);
+ i3c_device_getstatus_format1(sport->i3cdev, &status);
+ /*
+ * Target side needs some time to fill data into fifo. Target side may not
+ * have hardware update status in real time. Software update status always
+ * needs some delays.
+ *
+ * Generally, target side have circular buffer in memory, it will be moved
+ * into FIFO by CPU or DMA. 'status' just show if circular buffer empty. But
+ * there are gap, especially CPU have not response irq to fill FIFO in time.
+ * So xfers.actual will be zero, wait for little time to avoid flood
+ * transfer in i3c bus.
+ */
+ usleep_range(I3C_TTY_YIELD_US, 10 * I3C_TTY_YIELD_US);
+ retry--;
+
+ } while (retry && (status & BIT(0)));
+
+ tty_flip_buffer_push(&sport->port);
+}
+
+static void tty_i3c_txwork(struct work_struct *work)
+{
+ struct ttyi3c_port *sport = container_of(work, struct ttyi3c_port, txwork);
+ struct i3c_priv_xfer xfers;
+ u32 retry = I3C_TTY_RETRY;
+ unsigned long flags;
+ int ret;
+
+ xfers.rnw = 0;
+ xfers.data.out = sport->tx_buff;
+
+ while (!kfifo_is_empty(&sport->port.xmit_fifo)) {
+ spin_lock_irqsave(&sport->xlock, flags);
+ xfers.len = kfifo_out_peek(&sport->port.xmit_fifo, sport->tx_buff,
+ I3C_TTY_TRANS_SIZE);
+ spin_unlock_irqrestore(&sport->xlock, flags);
+ ret = i3c_device_do_priv_xfers(sport->i3cdev, &xfers, 1);
+ if (ret) {
+ /*
+ * Target side may not move data out of FIFO. delay can't resolve problem,
+ * just reduce some possiblity. Target can't end I3C SDR mode write
+ * transfer, discard data is reasonable when FIFO overrun.
+ */
+ usleep_range(I3C_TTY_YIELD_US, 10 * I3C_TTY_YIELD_US);
+ retry--;
+ } else {
+ retry = I3C_TTY_RETRY;
+ }
+
+ if (ret == 0 || retry == 0) {
+ /* when retry == 0, means need discard the data */
+ spin_lock_irqsave(&sport->xlock, flags);
+ ret = kfifo_out(&sport->port.xmit_fifo, sport->tx_buff, xfers.len);
+ spin_unlock_irqrestore(&sport->xlock, flags);
+ }
+ }
+
+ spin_lock_irqsave(&sport->xlock, flags);
+ if (kfifo_len(&sport->port.xmit_fifo) < WAKEUP_CHARS)
+ tty_port_tty_wakeup(&sport->port);
+ spin_unlock_irqrestore(&sport->xlock, flags);
+}
+
+static int i3c_probe(struct i3c_device *i3cdev)
+{
+ struct ttyi3c_port *sport;
+ struct device *tty_dev;
+ struct i3c_ibi_setup req;
+ int minor;
+ int ret;
+
+ sport = devm_kzalloc(&i3cdev->dev, sizeof(*sport), GFP_KERNEL);
+ if (!sport)
+ return -ENOMEM;
+
+ sport->i3cdev = i3cdev;
+
+ dev_set_drvdata(&i3cdev->dev, sport);
+
+ req.max_payload_len = 8;
+ req.num_slots = 4;
+ req.handler = &i3c_controller_irq_handler;
+
+ ret = i3c_device_request_ibi(i3cdev, &req);
+ if (ret)
+ return -EINVAL;
+
+ mutex_lock(&i3c_tty_minors_lock);
+ minor = idr_alloc(&i3c_tty_minors, sport, 0, I3C_TTY_MINORS, GFP_KERNEL);
+ mutex_unlock(&i3c_tty_minors_lock);
+
+ if (minor < 0) {
+ ret = -EINVAL;
+ goto err_idr_alloc;
+ }
+
+ spin_lock_init(&sport->xlock);
+ INIT_WORK(&sport->txwork, tty_i3c_txwork);
+ INIT_WORK(&sport->rxwork, tty_i3c_rxwork);
+ init_completion(&sport->txcomplete);
+
+ tty_port_init(&sport->port);
+ sport->port.ops = &i3c_port_ops;
+
+ tty_dev = tty_port_register_device(&sport->port, i3c_tty_driver, minor,
+ &i3cdev->dev);
+ if (IS_ERR(tty_dev)) {
+ ret = PTR_ERR(tty_dev);
+ goto err_tty_port_register;
+ }
+
+ sport->minor = minor;
+
+ return 0;
+
+err_tty_port_register:
+ tty_port_put(&sport->port);
+
+ mutex_lock(&i3c_tty_minors_lock);
+ idr_remove(&i3c_tty_minors, minor);
+ mutex_unlock(&i3c_tty_minors_lock);
+
+err_idr_alloc:
+ i3c_device_free_ibi(i3cdev);
+
+ return ret;
+}
+
+void i3c_remove(struct i3c_device *dev)
+{
+ struct ttyi3c_port *sport = dev_get_drvdata(&dev->dev);
+
+ tty_port_unregister_device(&sport->port, i3c_tty_driver, sport->minor);
+ cancel_work_sync(&sport->txwork);
+
+ tty_port_put(&sport->port);
+
+ mutex_lock(&i3c_tty_minors_lock);
+ idr_remove(&i3c_tty_minors, sport->minor);
+ mutex_unlock(&i3c_tty_minors_lock);
+
+ i3c_device_free_ibi(sport->i3cdev);
+}
+
+static struct i3c_driver i3c_driver = {
+ .driver = {
+ .name = "ttyi3c",
+ },
+ .probe = i3c_probe,
+ .remove = i3c_remove,
+ .id_table = i3c_ids,
+};
+
+static int __init i3c_tty_init(void)
+{
+ int ret;
+
+ i3c_tty_driver = tty_alloc_driver(I3C_TTY_MINORS,
+ TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV);
+
+ if (IS_ERR(i3c_tty_driver))
+ return PTR_ERR(i3c_tty_driver);
+
+ i3c_tty_driver->driver_name = "ttyI3C";
+ i3c_tty_driver->name = "ttyI3C";
+ i3c_tty_driver->minor_start = 0,
+ i3c_tty_driver->type = TTY_DRIVER_TYPE_SERIAL,
+ i3c_tty_driver->subtype = SERIAL_TYPE_NORMAL,
+ i3c_tty_driver->init_termios = tty_std_termios;
+ i3c_tty_driver->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL |
+ CLOCAL;
+ i3c_tty_driver->init_termios.c_lflag = 0;
+
+ tty_set_operations(i3c_tty_driver, &i3c_tty_ops);
+
+ ret = tty_register_driver(i3c_tty_driver);
+ if (ret)
+ goto err_tty_register_driver;
+
+ ret = i3c_driver_register(&i3c_driver);
+ if (ret)
+ goto err_i3c_driver_register;
+
+ return 0;
+
+err_i3c_driver_register:
+ tty_unregister_driver(i3c_tty_driver);
+
+err_tty_register_driver:
+ tty_driver_kref_put(i3c_tty_driver);
+
+ return ret;
+}
+
+static void __exit i3c_tty_exit(void)
+{
+ i3c_driver_unregister(&i3c_driver);
+ tty_unregister_driver(i3c_tty_driver);
+ tty_driver_kref_put(i3c_tty_driver);
+ idr_destroy(&i3c_tty_minors);
+}
+
+module_init(i3c_tty_init);
+module_exit(i3c_tty_exit);
+
+MODULE_LICENSE("GPL");
--
2.34.1


2024-01-10 18:01:14

by Frank Li

[permalink] [raw]
Subject: [PATCH v2 6/7] i3c: add API i3c_dev_gettstatus_format1() to get target device status

I3C standard 5.1.9.3.15 Get Device Status (GETSTATUS):
Get request for one I3C Target Device to return its current status.

Add API to fetch it with format1.

Signed-off-by: Frank Li <[email protected]>
---
drivers/i3c/device.c | 24 ++++++++++++++++++++++++
drivers/i3c/internals.h | 1 +
drivers/i3c/master.c | 26 ++++++++++++++++++++++++++
include/linux/i3c/device.h | 1 +
4 files changed, 52 insertions(+)

diff --git a/drivers/i3c/device.c b/drivers/i3c/device.c
index 1a6a8703dbc3a..aa26cf50ab9c6 100644
--- a/drivers/i3c/device.c
+++ b/drivers/i3c/device.c
@@ -196,6 +196,30 @@ void i3c_device_free_ibi(struct i3c_device *dev)
}
EXPORT_SYMBOL_GPL(i3c_device_free_ibi);

+/**
+ * i3c_device_getstatus_format1() - Get device status with format 1.
+ * @dev: device for which you want to get status.
+ * @status: I3C status format 1
+ *
+ * Return: 0 in case of success, a negative error core otherwise.
+ */
+int i3c_device_getstatus_format1(struct i3c_device *dev, u16 *status)
+{
+ int ret = -EINVAL;
+
+ if (!status)
+ return -EINVAL;
+
+ i3c_bus_normaluse_lock(dev->bus);
+ if (dev->desc)
+ ret = i3c_dev_getstatus_format1_locked(dev->desc, status);
+
+ i3c_bus_normaluse_unlock(dev->bus);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(i3c_device_getstatus_format1);
+
/**
* i3cdev_to_dev() - Returns the device embedded in @i3cdev
* @i3cdev: I3C device
diff --git a/drivers/i3c/internals.h b/drivers/i3c/internals.h
index 908a807badaf9..976ad26ca79c2 100644
--- a/drivers/i3c/internals.h
+++ b/drivers/i3c/internals.h
@@ -24,4 +24,5 @@ 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_format1_locked(struct i3c_dev_desc *dev, u16 *status);
#endif /* I3C_INTERNAL_H */
diff --git a/drivers/i3c/master.c b/drivers/i3c/master.c
index d3b56c9f601e2..81611a3e3585a 100644
--- a/drivers/i3c/master.c
+++ b/drivers/i3c/master.c
@@ -2923,6 +2923,32 @@ void i3c_dev_free_ibi_locked(struct i3c_dev_desc *dev)
dev->ibi = NULL;
}

+int i3c_dev_getstatus_format1_locked(struct i3c_dev_desc *dev, u16 *status)
+{
+ struct i3c_master_controller *master = i3c_dev_get_master(dev);
+ struct i3c_ccc_getstatus *format1;
+ struct i3c_ccc_cmd_dest dest;
+ struct i3c_ccc_cmd cmd;
+ int ret;
+
+ format1 = i3c_ccc_cmd_dest_init(&dest, dev->info.dyn_addr, sizeof(*format1));
+ if (!format1)
+ 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;
+
+ *status = be16_to_cpu(format1->status);
+
+out:
+ i3c_ccc_cmd_dest_cleanup(&dest);
+
+ return ret;
+}
+
static int __init i3c_init(void)
{
int res;
diff --git a/include/linux/i3c/device.h b/include/linux/i3c/device.h
index ef6217da8253b..5f511bd400f11 100644
--- a/include/linux/i3c/device.h
+++ b/include/linux/i3c/device.h
@@ -345,4 +345,5 @@ void i3c_device_free_ibi(struct i3c_device *dev);
int i3c_device_enable_ibi(struct i3c_device *dev);
int i3c_device_disable_ibi(struct i3c_device *dev);

+int i3c_device_getstatus_format1(struct i3c_device *dev, u16 *status);
#endif /* I3C_DEV_H */
--
2.34.1


2024-01-11 10:02:40

by kernel test robot

[permalink] [raw]
Subject: Re: [PATCH v2 4/7] i3c: target: add svc target controller support

Hi Frank,

kernel test robot noticed the following build warnings:

[auto build test WARNING on tty/tty-testing]
[also build test WARNING on tty/tty-next tty/tty-linus robh/for-next linus/master v6.7 next-20240111]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url: https://github.com/intel-lab-lkp/linux/commits/Frank-Li/i3c-add-target-mode-support/20240111-015711
base: https://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty.git tty-testing
patch link: https://lore.kernel.org/r/20240110175221.2335480-5-Frank.Li%40nxp.com
patch subject: [PATCH v2 4/7] i3c: target: add svc target controller support
config: powerpc-allmodconfig (https://download.01.org/0day-ci/archive/20240111/[email protected]/config)
compiler: clang version 18.0.0git (https://github.com/llvm/llvm-project 9bde5becb44ea071f5e1fa1f5d4071dc8788b18c)
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20240111/[email protected]/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <[email protected]>
| Closes: https://lore.kernel.org/oe-kbuild-all/[email protected]/

All warnings (new ones prefixed by >>):

In file included from include/linux/io.h:13:
In file included from arch/powerpc/include/asm/io.h:24:
In file included from include/linux/mm.h:1084:
In file included from include/linux/huge_mm.h:8:
In file included from include/linux/fs.h:33:
In file included from include/linux/percpu-rwsem.h:7:
In file included from include/linux/rcuwait.h:6:
In file included from include/linux/sched/signal.h:6:
include/linux/signal.h:186:1: warning: array index 1 is past the end of the array (that has type 'unsigned long[1]') [-Warray-bounds]
186 | _SIG_SET_OP(signotset, _sig_not)
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
include/linux/signal.h:176:10: note: expanded from macro '_SIG_SET_OP'
176 | case 2: set->sig[1] = op(set->sig[1]); \
| ^ ~
arch/powerpc/include/uapi/asm/signal.h:18:2: note: array 'sig' declared here
18 | unsigned long sig[_NSIG_WORDS];
| ^
In file included from drivers/i3c/target/svc-i3c-target.c:14:
In file included from include/linux/interrupt.h:11:
In file included from include/linux/hardirq.h:11:
In file included from arch/powerpc/include/asm/hardirq.h:6:
In file included from include/linux/irq.h:20:
In file included from include/linux/io.h:13:
In file included from arch/powerpc/include/asm/io.h:24:
In file included from include/linux/mm.h:1084:
In file included from include/linux/huge_mm.h:8:
In file included from include/linux/fs.h:33:
In file included from include/linux/percpu-rwsem.h:7:
In file included from include/linux/rcuwait.h:6:
In file included from include/linux/sched/signal.h:6:
include/linux/signal.h:197:10: warning: array index 1 is past the end of the array (that has type 'unsigned long[1]') [-Warray-bounds]
197 | case 2: set->sig[1] = 0;
| ^ ~
arch/powerpc/include/uapi/asm/signal.h:18:2: note: array 'sig' declared here
18 | unsigned long sig[_NSIG_WORDS];
| ^
In file included from drivers/i3c/target/svc-i3c-target.c:14:
In file included from include/linux/interrupt.h:11:
In file included from include/linux/hardirq.h:11:
In file included from arch/powerpc/include/asm/hardirq.h:6:
In file included from include/linux/irq.h:20:
In file included from include/linux/io.h:13:
In file included from arch/powerpc/include/asm/io.h:24:
In file included from include/linux/mm.h:1084:
In file included from include/linux/huge_mm.h:8:
In file included from include/linux/fs.h:33:
In file included from include/linux/percpu-rwsem.h:7:
In file included from include/linux/rcuwait.h:6:
In file included from include/linux/sched/signal.h:6:
include/linux/signal.h:210:10: warning: array index 1 is past the end of the array (that has type 'unsigned long[1]') [-Warray-bounds]
210 | case 2: set->sig[1] = -1;
| ^ ~
arch/powerpc/include/uapi/asm/signal.h:18:2: note: array 'sig' declared here
18 | unsigned long sig[_NSIG_WORDS];
| ^
In file included from drivers/i3c/target/svc-i3c-target.c:14:
In file included from include/linux/interrupt.h:11:
In file included from include/linux/hardirq.h:11:
In file included from arch/powerpc/include/asm/hardirq.h:6:
In file included from include/linux/irq.h:20:
In file included from include/linux/io.h:13:
In file included from arch/powerpc/include/asm/io.h:24:
In file included from include/linux/mm.h:1084:
In file included from include/linux/huge_mm.h:8:
In file included from include/linux/fs.h:33:
In file included from include/linux/percpu-rwsem.h:7:
In file included from include/linux/rcuwait.h:6:
In file included from include/linux/sched/signal.h:6:
include/linux/signal.h:241:10: warning: array index 1 is past the end of the array (that has type 'unsigned long[1]') [-Warray-bounds]
241 | case 2: set->sig[1] = 0;
| ^ ~
arch/powerpc/include/uapi/asm/signal.h:18:2: note: array 'sig' declared here
18 | unsigned long sig[_NSIG_WORDS];
| ^
In file included from drivers/i3c/target/svc-i3c-target.c:14:
In file included from include/linux/interrupt.h:11:
In file included from include/linux/hardirq.h:11:
In file included from arch/powerpc/include/asm/hardirq.h:6:
In file included from include/linux/irq.h:20:
In file included from include/linux/io.h:13:
In file included from arch/powerpc/include/asm/io.h:24:
In file included from include/linux/mm.h:1084:
In file included from include/linux/huge_mm.h:8:
In file included from include/linux/fs.h:33:
In file included from include/linux/percpu-rwsem.h:7:
In file included from include/linux/rcuwait.h:6:
In file included from include/linux/sched/signal.h:6:
include/linux/signal.h:254:10: warning: array index 1 is past the end of the array (that has type 'unsigned long[1]') [-Warray-bounds]
254 | case 2: set->sig[1] = -1;
| ^ ~
arch/powerpc/include/uapi/asm/signal.h:18:2: note: array 'sig' declared here
18 | unsigned long sig[_NSIG_WORDS];
| ^
drivers/i3c/target/svc-i3c-target.c:211:40: warning: no previous prototype for function 'svc_i3c_get_features' [-Wmissing-prototypes]
211 | const struct i3c_target_ctrl_features *svc_i3c_get_features(struct i3c_target_ctrl *ctrl)
| ^
drivers/i3c/target/svc-i3c-target.c:211:7: note: declare 'static' if the function is not intended to be used outside of this translation unit
211 | const struct i3c_target_ctrl_features *svc_i3c_get_features(struct i3c_target_ctrl *ctrl)
| ^
| static
>> drivers/i3c/target/svc-i3c-target.c:268:63: warning: omitting the parameter name in a function definition is a C23 extension [-Wc23-extensions]
268 | static int svc_i3c_target_queue(struct i3c_request *req, gfp_t)
| ^
drivers/i3c/target/svc-i3c-target.c:666:5: warning: no previous prototype for function 'svc_i3c_fifo_status' [-Wmissing-prototypes]
666 | int svc_i3c_fifo_status(struct i3c_target_ctrl *ctrl, bool tx)
| ^
drivers/i3c/target/svc-i3c-target.c:666:1: note: declare 'static' if the function is not intended to be used outside of this translation unit
666 | int svc_i3c_fifo_status(struct i3c_target_ctrl *ctrl, bool tx)
| ^
| static
52 warnings and 5 errors generated.


vim +268 drivers/i3c/target/svc-i3c-target.c

267
> 268 static int svc_i3c_target_queue(struct i3c_request *req, gfp_t)
269 {
270 struct svc_i3c_target *svc;
271 struct list_head *q;
272 unsigned long flags;
273 spinlock_t *lk;
274
275 svc = dev_get_drvdata(&req->ctrl->dev);
276 if (!svc)
277 return -EINVAL;
278
279 if (req->tx) {
280 q = &svc->txq;
281 lk = &svc->txq_lock;
282 } else {
283 q = &svc->rxq;
284 lk = &svc->rxq_lock;
285 }
286
287 spin_lock_irqsave(lk, flags);
288 list_add_tail(&req->list, q);
289 spin_unlock_irqrestore(lk, flags);
290
291 if (req->tx)
292 svc_i3c_fill_txfifo(svc);
293
294 if (req->tx)
295 writel_relaxed(I3C_SINT_TXSEND, svc->regs + I3C_SINTSET);
296 else
297 writel_relaxed(I3C_SINT_RXPEND, svc->regs + I3C_SINTSET);
298
299 return 0;
300 }
301

--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki

2024-01-11 13:50:43

by kernel test robot

[permalink] [raw]
Subject: Re: [PATCH v2 4/7] i3c: target: add svc target controller support

Hi Frank,

kernel test robot noticed the following build warnings:

[auto build test WARNING on tty/tty-testing]
[also build test WARNING on tty/tty-next tty/tty-linus robh/for-next linus/master v6.7 next-20240111]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url: https://github.com/intel-lab-lkp/linux/commits/Frank-Li/i3c-add-target-mode-support/20240111-015711
base: https://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty.git tty-testing
patch link: https://lore.kernel.org/r/20240110175221.2335480-5-Frank.Li%40nxp.com
patch subject: [PATCH v2 4/7] i3c: target: add svc target controller support
config: x86_64-allmodconfig (https://download.01.org/0day-ci/archive/20240111/[email protected]/config)
compiler: ClangBuiltLinux clang version 17.0.6 (https://github.com/llvm/llvm-project 6009708b4367171ccdbf4b5905cb6a803753fe18)
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20240111/[email protected]/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <[email protected]>
| Closes: https://lore.kernel.org/oe-kbuild-all/[email protected]/

All warnings (new ones prefixed by >>):

>> drivers/i3c/target/svc-i3c-target.c:211:40: warning: no previous prototype for function 'svc_i3c_get_features' [-Wmissing-prototypes]
211 | const struct i3c_target_ctrl_features *svc_i3c_get_features(struct i3c_target_ctrl *ctrl)
| ^
drivers/i3c/target/svc-i3c-target.c:211:7: note: declare 'static' if the function is not intended to be used outside of this translation unit
211 | const struct i3c_target_ctrl_features *svc_i3c_get_features(struct i3c_target_ctrl *ctrl)
| ^
| static
>> drivers/i3c/target/svc-i3c-target.c:268:63: warning: omitting the parameter name in a function definition is a C2x extension [-Wc2x-extensions]
268 | static int svc_i3c_target_queue(struct i3c_request *req, gfp_t)
| ^
>> drivers/i3c/target/svc-i3c-target.c:666:5: warning: no previous prototype for function 'svc_i3c_fifo_status' [-Wmissing-prototypes]
666 | int svc_i3c_fifo_status(struct i3c_target_ctrl *ctrl, bool tx)
| ^
drivers/i3c/target/svc-i3c-target.c:666:1: note: declare 'static' if the function is not intended to be used outside of this translation unit
666 | int svc_i3c_fifo_status(struct i3c_target_ctrl *ctrl, bool tx)
| ^
| static
3 warnings generated.


vim +/svc_i3c_get_features +211 drivers/i3c/target/svc-i3c-target.c

210
> 211 const struct i3c_target_ctrl_features *svc_i3c_get_features(struct i3c_target_ctrl *ctrl)
212 {
213 struct svc_i3c_target *svc;
214
215 svc = dev_get_drvdata(&ctrl->dev);
216
217 if (!svc)
218 return NULL;
219
220 return &svc->features;
221 }
222
223 static void svc_i3c_queue_complete(struct svc_i3c_target *svc, struct i3c_request *complete)
224 {
225 unsigned long flags;
226
227 spin_lock_irqsave(&svc->cq_lock, flags);
228 list_add_tail(&complete->list, &svc->cq);
229 spin_unlock_irqrestore(&svc->cq_lock, flags);
230 queue_work(svc->workqueue, &svc->work);
231 }
232
233 static void svc_i3c_fill_txfifo(struct svc_i3c_target *svc)
234 {
235 struct i3c_request *req, *complete = NULL;
236 unsigned long flags;
237 int val;
238
239 spin_lock_irqsave(&svc->txq_lock, flags);
240 while ((!!(req = list_first_entry_or_null(&svc->txq, struct i3c_request, list))) &&
241 !((readl_relaxed(svc->regs + I3C_SDATACTRL) & I3C_SDATACTRL_TXFULL_MASK))) {
242 while (!(readl_relaxed(svc->regs + I3C_SDATACTRL)
243 & I3C_SDATACTRL_TXFULL_MASK)) {
244 val = *(u8 *)(req->buf + req->actual);
245
246 if (req->actual + 1 == req->length)
247 writel_relaxed(val, svc->regs + I3C_SWDATAE);
248 else
249 writel_relaxed(val, svc->regs + I3C_SWDATAB);
250
251 req->actual++;
252
253 if (req->actual == req->length) {
254 list_del(&req->list);
255 complete = req;
256 spin_unlock_irqrestore(&svc->txq_lock, flags);
257
258 svc_i3c_queue_complete(svc, complete);
259
260 spin_lock_irqsave(&svc->txq_lock, flags);
261 break;
262 }
263 }
264 }
265 spin_unlock_irqrestore(&svc->txq_lock, flags);
266 }
267
> 268 static int svc_i3c_target_queue(struct i3c_request *req, gfp_t)
269 {
270 struct svc_i3c_target *svc;
271 struct list_head *q;
272 unsigned long flags;
273 spinlock_t *lk;
274
275 svc = dev_get_drvdata(&req->ctrl->dev);
276 if (!svc)
277 return -EINVAL;
278
279 if (req->tx) {
280 q = &svc->txq;
281 lk = &svc->txq_lock;
282 } else {
283 q = &svc->rxq;
284 lk = &svc->rxq_lock;
285 }
286
287 spin_lock_irqsave(lk, flags);
288 list_add_tail(&req->list, q);
289 spin_unlock_irqrestore(lk, flags);
290
291 if (req->tx)
292 svc_i3c_fill_txfifo(svc);
293
294 if (req->tx)
295 writel_relaxed(I3C_SINT_TXSEND, svc->regs + I3C_SINTSET);
296 else
297 writel_relaxed(I3C_SINT_RXPEND, svc->regs + I3C_SINTSET);
298
299 return 0;
300 }
301

--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki

2024-01-11 23:46:25

by kernel test robot

[permalink] [raw]
Subject: Re: [PATCH v2 3/7] Documentation: i3c: Add I3C target mode controller and function

Hi Frank,

kernel test robot noticed the following build warnings:

[auto build test WARNING on tty/tty-testing]
[also build test WARNING on tty/tty-next tty/tty-linus robh/for-next linus/master v6.7 next-20240111]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url: https://github.com/intel-lab-lkp/linux/commits/Frank-Li/i3c-add-target-mode-support/20240111-015711
base: https://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty.git tty-testing
patch link: https://lore.kernel.org/r/20240110175221.2335480-4-Frank.Li%40nxp.com
patch subject: [PATCH v2 3/7] Documentation: i3c: Add I3C target mode controller and function
reproduce: (https://download.01.org/0day-ci/archive/20240112/[email protected]/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <[email protected]>
| Closes: https://lore.kernel.org/oe-kbuild-all/[email protected]/

All warnings (new ones prefixed by >>):

>> Warning: Documentation/driver-api/i3c/target/i3c-target-cfs.rst references a file that doesn't exist: Documentation/I3C/target/pci-target.rst
>> Documentation/driver-api/i3c/target/i3c-target.rst:38: WARNING: Title underline too short.
>> Documentation/driver-api/i3c/target/i3c-target-cfs.rst:73: WARNING: Title underline too short.
>> Documentation/driver-api/i3c/target/i3c-tty-howto.rst:45: WARNING: Title underline too short.

--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki

2024-01-12 07:38:59

by Krzysztof Kozlowski

[permalink] [raw]
Subject: Re: [PATCH v2 2/7] dt-bindings: i3c: svc: add compatible string i3c: silvaco,i3c-target-v1

On 10/01/2024 18:52, Frank Li wrote:
> Add compatible string 'silvaco,i3c-target-v1' for target mode.

Your subject has some multiple prefixes? Why there is one more ":"?
Just: add XYZ device


>
> Signed-off-by: Frank Li <[email protected]>
> ---
> .../devicetree/bindings/i3c/silvaco,i3c-master.yaml | 7 ++++---
> 1 file changed, 4 insertions(+), 3 deletions(-)
>
> diff --git a/Documentation/devicetree/bindings/i3c/silvaco,i3c-master.yaml b/Documentation/devicetree/bindings/i3c/silvaco,i3c-master.yaml
> index 133855f11b4f5..17849c91d4d2b 100644
> --- a/Documentation/devicetree/bindings/i3c/silvaco,i3c-master.yaml
> +++ b/Documentation/devicetree/bindings/i3c/silvaco,i3c-master.yaml
> @@ -4,7 +4,7 @@
> $id: http://devicetree.org/schemas/i3c/silvaco,i3c-master.yaml#
> $schema: http://devicetree.org/meta-schemas/core.yaml#
>
> -title: Silvaco I3C master
> +title: Silvaco I3C master/target
>
> maintainers:
> - Conor Culhane <[email protected]>
> @@ -14,8 +14,9 @@ allOf:
>
> properties:
> compatible:
> - const: silvaco,i3c-master-v1

NAK, you got comment, didn't you? Why did you ignore it? It's like third
time you try to push it ignoring what we keep asking. Pushing the same
without resolving anything in previous discussion is not acceptable and
it feels like waste of my time.


> -

Why are you removing the blank line?


Best regards,
Krzysztof


2024-01-12 15:32:27

by Frank Li

[permalink] [raw]
Subject: Re: [PATCH v2 2/7] dt-bindings: i3c: svc: add compatible string i3c: silvaco,i3c-target-v1

On Fri, Jan 12, 2024 at 08:38:39AM +0100, Krzysztof Kozlowski wrote:
> On 10/01/2024 18:52, Frank Li wrote:
> > Add compatible string 'silvaco,i3c-target-v1' for target mode.
>
> Your subject has some multiple prefixes? Why there is one more ":"?
> Just: add XYZ device
>
>
> >
> > Signed-off-by: Frank Li <[email protected]>
> > ---
> > .../devicetree/bindings/i3c/silvaco,i3c-master.yaml | 7 ++++---
> > 1 file changed, 4 insertions(+), 3 deletions(-)
> >
> > diff --git a/Documentation/devicetree/bindings/i3c/silvaco,i3c-master.yaml b/Documentation/devicetree/bindings/i3c/silvaco,i3c-master.yaml
> > index 133855f11b4f5..17849c91d4d2b 100644
> > --- a/Documentation/devicetree/bindings/i3c/silvaco,i3c-master.yaml
> > +++ b/Documentation/devicetree/bindings/i3c/silvaco,i3c-master.yaml
> > @@ -4,7 +4,7 @@
> > $id: http://devicetree.org/schemas/i3c/silvaco,i3c-master.yaml#
> > $schema: http://devicetree.org/meta-schemas/core.yaml#
> >
> > -title: Silvaco I3C master
> > +title: Silvaco I3C master/target
> >
> > maintainers:
> > - Conor Culhane <[email protected]>
> > @@ -14,8 +14,9 @@ allOf:
> >
> > properties:
> > compatible:
> > - const: silvaco,i3c-master-v1
>
> NAK, you got comment, didn't you? Why did you ignore it? It's like third
> time you try to push it ignoring what we keep asking. Pushing the same
> without resolving anything in previous discussion is not acceptable and
> it feels like waste of my time.

I review previous comments. The previous RFC patches and I just want I3C
expert review to check if there are comments about whole software
architecture. Of course, thank you for your comments about "slave".

Go back this binding doc problem.

"No, it's the same device.

Anyway, this was not tested.

Please use scripts/get_maintainers.pl to get a list of necessary people
and lists to CC. It might happen, that command when run on an older
kernel, gives you outdated entries. Therefore please be sure you base
your patches on recent Linux kernel.

You missed at least devicetree list (maybe more), so this won't be
tested by automated tooling. Performing review on untested code might be
a waste of time, thus I will skip this patch entirely till you follow
the process allowing the patch to be tested.

Please kindly resend and include all necessary To/Cc entries.
"

It is the same devices, work at difference mode (master and target).
what's do you want to change to?

Copy to new file like pci/pci-ep? all context is the same, except for
compatible string.

Frank
>
>
> > -
>
> Why are you removing the blank line?
>
>
> Best regards,
> Krzysztof
>

2024-01-12 15:51:46

by Krzysztof Kozlowski

[permalink] [raw]
Subject: Re: [PATCH v2 2/7] dt-bindings: i3c: svc: add compatible string i3c: silvaco,i3c-target-v1

On 12/01/2024 16:31, Frank Li wrote:
> I review previous comments. The previous RFC patches and I just want I3C
> expert review to check if there are comments about whole software
> architecture. Of course, thank you for your comments about "slave".
>
> Go back this binding doc problem.
>
> "No, it's the same device.
>
> Anyway, this was not tested.
>
> Please use scripts/get_maintainers.pl to get a list of necessary people
> and lists to CC. It might happen, that command when run on an older
> kernel, gives you outdated entries. Therefore please be sure you base
> your patches on recent Linux kernel.
>
> You missed at least devicetree list (maybe more), so this won't be
> tested by automated tooling. Performing review on untested code might be
> a waste of time, thus I will skip this patch entirely till you follow
> the process allowing the patch to be tested.
>
> Please kindly resend and include all necessary To/Cc entries.
> "
>
> It is the same devices, work at difference mode (master and target).
> what's do you want to change to?
>
> Copy to new file like pci/pci-ep? all context is the same, except for
> compatible string.
>

Apologies, I mixed up a bit patches, so this was not obvious. I meant
this comment:

https://lore.kernel.org/all/[email protected]/

There is no indication in your commit msg that these concerns were
addressed.

Best regards,
Krzysztof


2024-01-12 16:00:32

by Krzysztof Kozlowski

[permalink] [raw]
Subject: Re: [PATCH v2 2/7] dt-bindings: i3c: svc: add compatible string i3c: silvaco,i3c-target-v1

On 12/01/2024 16:50, Krzysztof Kozlowski wrote:
> On 12/01/2024 16:31, Frank Li wrote:
>> I review previous comments. The previous RFC patches and I just want I3C
>> expert review to check if there are comments about whole software
>> architecture. Of course, thank you for your comments about "slave".
>>
>> Go back this binding doc problem.
>>
>> "No, it's the same device.
>>
>> Anyway, this was not tested.
>>
>> Please use scripts/get_maintainers.pl to get a list of necessary people
>> and lists to CC. It might happen, that command when run on an older
>> kernel, gives you outdated entries. Therefore please be sure you base
>> your patches on recent Linux kernel.
>>
>> You missed at least devicetree list (maybe more), so this won't be
>> tested by automated tooling. Performing review on untested code might be
>> a waste of time, thus I will skip this patch entirely till you follow
>> the process allowing the patch to be tested.
>>
>> Please kindly resend and include all necessary To/Cc entries.
>> "
>>
>> It is the same devices, work at difference mode (master and target).
>> what's do you want to change to?
>>
>> Copy to new file like pci/pci-ep? all context is the same, except for
>> compatible string.
>>
>
> Apologies, I mixed up a bit patches, so this was not obvious. I meant
> this comment:
>
> https://lore.kernel.org/all/[email protected]/
>
> There is no indication in your commit msg that these concerns were
> addressed.

And here:

https://lore.kernel.org/all/[email protected]/

Best regards,
Krzysztof


2024-01-12 16:06:53

by Frank Li

[permalink] [raw]
Subject: Re: [PATCH v2 2/7] dt-bindings: i3c: svc: add compatible string i3c: silvaco,i3c-target-v1

On Fri, Jan 12, 2024 at 04:50:25PM +0100, Krzysztof Kozlowski wrote:
> On 12/01/2024 16:31, Frank Li wrote:
> > I review previous comments. The previous RFC patches and I just want I3C
> > expert review to check if there are comments about whole software
> > architecture. Of course, thank you for your comments about "slave".
> >
> > Go back this binding doc problem.
> >
> > "No, it's the same device.
> >
> > Anyway, this was not tested.
> >
> > Please use scripts/get_maintainers.pl to get a list of necessary people
> > and lists to CC. It might happen, that command when run on an older
> > kernel, gives you outdated entries. Therefore please be sure you base
> > your patches on recent Linux kernel.
> >
> > You missed at least devicetree list (maybe more), so this won't be
> > tested by automated tooling. Performing review on untested code might be
> > a waste of time, thus I will skip this patch entirely till you follow
> > the process allowing the patch to be tested.
> >
> > Please kindly resend and include all necessary To/Cc entries.
> > "
> >
> > It is the same devices, work at difference mode (master and target).
> > what's do you want to change to?
> >
> > Copy to new file like pci/pci-ep? all context is the same, except for
> > compatible string.
> >
>
> Apologies, I mixed up a bit patches, so this was not obvious. I meant
> this comment:
>
> https://lore.kernel.org/all/[email protected]/
>
> There is no indication in your commit msg that these concerns were
> addressed.

Look like everyone already accecpted 'silvaco,i3c-master-v1'.

driver part:
https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git/commit/?id=8911eae9c8a947e5c1cc4fcce40473f1f5e475cd
dts part:
https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git/commit/?id=b8ec0f3b42a3498d5115d1fb1490082ab525747b

Frank

>
> Best regards,
> Krzysztof
>

2024-01-15 19:44:30

by Frank Li

[permalink] [raw]
Subject: Re: [PATCH v2 2/7] dt-bindings: i3c: svc: add compatible string i3c: silvaco,i3c-target-v1

On Fri, Jan 12, 2024 at 11:06:01AM -0500, Frank Li wrote:
> On Fri, Jan 12, 2024 at 04:50:25PM +0100, Krzysztof Kozlowski wrote:
> > On 12/01/2024 16:31, Frank Li wrote:
> > > I review previous comments. The previous RFC patches and I just want I3C
> > > expert review to check if there are comments about whole software
> > > architecture. Of course, thank you for your comments about "slave".
> > >
> > > Go back this binding doc problem.
> > >
> > > "No, it's the same device.
> > >
> > > Anyway, this was not tested.
> > >
> > > Please use scripts/get_maintainers.pl to get a list of necessary people
> > > and lists to CC. It might happen, that command when run on an older
> > > kernel, gives you outdated entries. Therefore please be sure you base
> > > your patches on recent Linux kernel.
> > >
> > > You missed at least devicetree list (maybe more), so this won't be
> > > tested by automated tooling. Performing review on untested code might be
> > > a waste of time, thus I will skip this patch entirely till you follow
> > > the process allowing the patch to be tested.
> > >
> > > Please kindly resend and include all necessary To/Cc entries.
> > > "
> > >
> > > It is the same devices, work at difference mode (master and target).
> > > what's do you want to change to?
> > >
> > > Copy to new file like pci/pci-ep? all context is the same, except for
> > > compatible string.
> > >
> >
> > Apologies, I mixed up a bit patches, so this was not obvious. I meant
> > this comment:
> >
> > https://lore.kernel.org/all/[email protected]/
> >
> > There is no indication in your commit msg that these concerns were
> > addressed.
>
> Look like everyone already accecpted 'silvaco,i3c-master-v1'.
>
> driver part:
> https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git/commit/?id=8911eae9c8a947e5c1cc4fcce40473f1f5e475cd
> dts part:
> https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git/commit/?id=b8ec0f3b42a3498d5115d1fb1490082ab525747b

@Krzysztof:
Patches were accepted after discussion, what you ponit to. So I
think everyone agree on the name 'silvaco,i3c-master-v1'.
I plan send next version to fix auto build error. Any additional
comments about this?

Frank

>
> Frank
>
> >
> > Best regards,
> > Krzysztof
> >

2024-01-15 20:38:57

by Krzysztof Kozlowski

[permalink] [raw]
Subject: Re: [PATCH v2 2/7] dt-bindings: i3c: svc: add compatible string i3c: silvaco,i3c-target-v1

On 15/01/2024 20:44, Frank Li wrote:
> On Fri, Jan 12, 2024 at 11:06:01AM -0500, Frank Li wrote:
>> On Fri, Jan 12, 2024 at 04:50:25PM +0100, Krzysztof Kozlowski wrote:
>>> On 12/01/2024 16:31, Frank Li wrote:
>>>> I review previous comments. The previous RFC patches and I just want I3C
>>>> expert review to check if there are comments about whole software
>>>> architecture. Of course, thank you for your comments about "slave".
>>>>
>>>> Go back this binding doc problem.
>>>>
>>>> "No, it's the same device.
>>>>
>>>> Anyway, this was not tested.
>>>>
>>>> Please use scripts/get_maintainers.pl to get a list of necessary people
>>>> and lists to CC. It might happen, that command when run on an older
>>>> kernel, gives you outdated entries. Therefore please be sure you base
>>>> your patches on recent Linux kernel.
>>>>
>>>> You missed at least devicetree list (maybe more), so this won't be
>>>> tested by automated tooling. Performing review on untested code might be
>>>> a waste of time, thus I will skip this patch entirely till you follow
>>>> the process allowing the patch to be tested.
>>>>
>>>> Please kindly resend and include all necessary To/Cc entries.
>>>> "
>>>>
>>>> It is the same devices, work at difference mode (master and target).
>>>> what's do you want to change to?
>>>>
>>>> Copy to new file like pci/pci-ep? all context is the same, except for
>>>> compatible string.
>>>>
>>>
>>> Apologies, I mixed up a bit patches, so this was not obvious. I meant
>>> this comment:
>>>
>>> https://lore.kernel.org/all/[email protected]/
>>>
>>> There is no indication in your commit msg that these concerns were
>>> addressed.
>>
>> Look like everyone already accecpted 'silvaco,i3c-master-v1'.
>>
>> driver part:
>> https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git/commit/?id=8911eae9c8a947e5c1cc4fcce40473f1f5e475cd
>> dts part:
>> https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git/commit/?id=b8ec0f3b42a3498d5115d1fb1490082ab525747b
>
> @Krzysztof:
> Patches were accepted after discussion, what you ponit to. So I
> think everyone agree on the name 'silvaco,i3c-master-v1'.
> I plan send next version to fix auto build error. Any additional
> comments about this?

I still do not see how did you address Rob's comment and his point is
valid. You just did not reply to it.

Best regards,
Krzysztof


2024-01-16 02:30:22

by Frank Li

[permalink] [raw]
Subject: Re: [PATCH v2 2/7] dt-bindings: i3c: svc: add compatible string i3c: silvaco,i3c-target-v1

On Mon, Jan 15, 2024 at 09:38:19PM +0100, Krzysztof Kozlowski wrote:
> On 15/01/2024 20:44, Frank Li wrote:
> > On Fri, Jan 12, 2024 at 11:06:01AM -0500, Frank Li wrote:
> >> On Fri, Jan 12, 2024 at 04:50:25PM +0100, Krzysztof Kozlowski wrote:
> >>> On 12/01/2024 16:31, Frank Li wrote:
> >>>> I review previous comments. The previous RFC patches and I just want I3C
> >>>> expert review to check if there are comments about whole software
> >>>> architecture. Of course, thank you for your comments about "slave".
> >>>>
> >>>> Go back this binding doc problem.
> >>>>
> >>>> "No, it's the same device.
> >>>>
> >>>> Anyway, this was not tested.
> >>>>
> >>>> Please use scripts/get_maintainers.pl to get a list of necessary people
> >>>> and lists to CC. It might happen, that command when run on an older
> >>>> kernel, gives you outdated entries. Therefore please be sure you base
> >>>> your patches on recent Linux kernel.
> >>>>
> >>>> You missed at least devicetree list (maybe more), so this won't be
> >>>> tested by automated tooling. Performing review on untested code might be
> >>>> a waste of time, thus I will skip this patch entirely till you follow
> >>>> the process allowing the patch to be tested.
> >>>>
> >>>> Please kindly resend and include all necessary To/Cc entries.
> >>>> "
> >>>>
> >>>> It is the same devices, work at difference mode (master and target).
> >>>> what's do you want to change to?
> >>>>
> >>>> Copy to new file like pci/pci-ep? all context is the same, except for
> >>>> compatible string.
> >>>>
> >>>
> >>> Apologies, I mixed up a bit patches, so this was not obvious. I meant
> >>> this comment:
> >>>
> >>> https://lore.kernel.org/all/[email protected]/
> >>>
> >>> There is no indication in your commit msg that these concerns were
> >>> addressed.
> >>
> >> Look like everyone already accecpted 'silvaco,i3c-master-v1'.
> >>
> >> driver part:
> >> https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git/commit/?id=8911eae9c8a947e5c1cc4fcce40473f1f5e475cd
> >> dts part:
> >> https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git/commit/?id=b8ec0f3b42a3498d5115d1fb1490082ab525747b
> >
> > @Krzysztof:
> > Patches were accepted after discussion, what you ponit to. So I
> > think everyone agree on the name 'silvaco,i3c-master-v1'.
> > I plan send next version to fix auto build error. Any additional
> > comments about this?
>
> I still do not see how did you address Rob's comment and his point is
> valid. You just did not reply to it.

See https://lore.kernel.org/imx/ZXCiaKfMYYShoiXK@lizhi-Precision-Tower-5810/

Frank

>
> Best regards,
> Krzysztof
>

2024-01-16 07:24:44

by Krzysztof Kozlowski

[permalink] [raw]
Subject: Re: [PATCH v2 2/7] dt-bindings: i3c: svc: add compatible string i3c: silvaco,i3c-target-v1

On 16/01/2024 03:29, Frank Li wrote:
>>> Patches were accepted after discussion, what you ponit to. So I
>>> think everyone agree on the name 'silvaco,i3c-master-v1'.
>>> I plan send next version to fix auto build error. Any additional
>>> comments about this?
>>
>> I still do not see how did you address Rob's comment and his point is
>> valid. You just did not reply to it.
>
> See https://lore.kernel.org/imx/ZXCiaKfMYYShoiXK@lizhi-Precision-Tower-5810/

First of all, that's not the answer to Rob's email, but some other
thread which is 99% ignored by Rob (unless he has filters for
"@Rob"...). Therefore no, it does not count as valid answer.

Second, explanation does not make sense. There is no argument granting
you exception from SoC specific compatibles.

Best regards,
Krzysztof


2024-01-16 09:31:35

by Conor Dooley

[permalink] [raw]
Subject: Re: [PATCH v2 2/7] dt-bindings: i3c: svc: add compatible string i3c: silvaco,i3c-target-v1

On Tue, Jan 16, 2024 at 08:24:20AM +0100, Krzysztof Kozlowski wrote:
> On 16/01/2024 03:29, Frank Li wrote:
> >>> Patches were accepted after discussion, what you ponit to. So I
> >>> think everyone agree on the name 'silvaco,i3c-master-v1'.
> >>> I plan send next version to fix auto build error. Any additional
> >>> comments about this?
> >>
> >> I still do not see how did you address Rob's comment and his point is
> >> valid. You just did not reply to it.
> >
> > See https://lore.kernel.org/imx/ZXCiaKfMYYShoiXK@lizhi-Precision-Tower-5810/
>
> First of all, that's not the answer to Rob's email, but some other
> thread which is 99% ignored by Rob (unless he has filters for
> "@Rob"...). Therefore no, it does not count as valid answer.
>
> Second, explanation does not make sense. There is no argument granting
> you exception from SoC specific compatibles.

The patch could have been applied two months ago had Frank done as
was requested (multiple times). I don't understand the resistance
towards doing so given the process has taken way way longer as a result.


Attachments:
(No filename) (1.08 kB)
signature.asc (235.00 B)
Download all attachments

2024-01-16 09:34:06

by Krzysztof Kozlowski

[permalink] [raw]
Subject: Re: [PATCH v2 2/7] dt-bindings: i3c: svc: add compatible string i3c: silvaco,i3c-target-v1

On 16/01/2024 10:30, Conor Dooley wrote:
> On Tue, Jan 16, 2024 at 08:24:20AM +0100, Krzysztof Kozlowski wrote:
>> On 16/01/2024 03:29, Frank Li wrote:
>>>>> Patches were accepted after discussion, what you ponit to. So I
>>>>> think everyone agree on the name 'silvaco,i3c-master-v1'.
>>>>> I plan send next version to fix auto build error. Any additional
>>>>> comments about this?
>>>>
>>>> I still do not see how did you address Rob's comment and his point is
>>>> valid. You just did not reply to it.
>>>
>>> See https://lore.kernel.org/imx/ZXCiaKfMYYShoiXK@lizhi-Precision-Tower-5810/
>>
>> First of all, that's not the answer to Rob's email, but some other
>> thread which is 99% ignored by Rob (unless he has filters for
>> "@Rob"...). Therefore no, it does not count as valid answer.
>>
>> Second, explanation does not make sense. There is no argument granting
>> you exception from SoC specific compatibles.
>
> The patch could have been applied two months ago had Frank done as
> was requested (multiple times). I don't understand the resistance
> towards doing so given the process has taken way way longer as a result.

I think that Rob's comment was just skipped and original master binding
was merged without addressing it. I don't want to repeat the same
process for the "target". Indeed I could point this earlier... if I only
knew that Rob pointed out that issue.

Best regards,
Krzysztof


2024-01-16 09:49:27

by Conor Dooley

[permalink] [raw]
Subject: Re: [PATCH v2 2/7] dt-bindings: i3c: svc: add compatible string i3c: silvaco,i3c-target-v1

On Tue, Jan 16, 2024 at 10:33:48AM +0100, Krzysztof Kozlowski wrote:
> On 16/01/2024 10:30, Conor Dooley wrote:
> > On Tue, Jan 16, 2024 at 08:24:20AM +0100, Krzysztof Kozlowski wrote:
> >> On 16/01/2024 03:29, Frank Li wrote:
> >>>>> Patches were accepted after discussion, what you ponit to. So I
> >>>>> think everyone agree on the name 'silvaco,i3c-master-v1'.
> >>>>> I plan send next version to fix auto build error. Any additional
> >>>>> comments about this?
> >>>>
> >>>> I still do not see how did you address Rob's comment and his point is
> >>>> valid. You just did not reply to it.
> >>>
> >>> See https://lore.kernel.org/imx/ZXCiaKfMYYShoiXK@lizhi-Precision-Tower-5810/
> >>
> >> First of all, that's not the answer to Rob's email, but some other
> >> thread which is 99% ignored by Rob (unless he has filters for
> >> "@Rob"...). Therefore no, it does not count as valid answer.
> >>
> >> Second, explanation does not make sense. There is no argument granting
> >> you exception from SoC specific compatibles.
> >
> > The patch could have been applied two months ago had Frank done as
> > was requested (multiple times). I don't understand the resistance
> > towards doing so given the process has taken way way longer as a result.
>
> I think that Rob's comment was just skipped and original master binding
> was merged without addressing it. I don't want to repeat the same
> process for the "target". Indeed I could point this earlier... if I only
> knew that Rob pointed out that issue.

Oh I think I got confused here. The context for this mail led me to
think that this was still trying to push the i3c-master-v1 stuff through
and I was commenting on my frustration with the resistance to applying
the feedback received. I didn't realise that this was for another
patch adding a target.

I think you already said it, but NAK to adding any more compatibles here
until the soc-specific compatible that was asked for for the imx93 is
added.

Thanks,
Conor.


Attachments:
(No filename) (1.97 kB)
signature.asc (235.00 B)
Download all attachments

2024-01-16 17:36:09

by Frank Li

[permalink] [raw]
Subject: Re: [PATCH v2 2/7] dt-bindings: i3c: svc: add compatible string i3c: silvaco,i3c-target-v1

On Tue, Jan 16, 2024 at 09:48:08AM +0000, Conor Dooley wrote:
> On Tue, Jan 16, 2024 at 10:33:48AM +0100, Krzysztof Kozlowski wrote:
> > On 16/01/2024 10:30, Conor Dooley wrote:
> > > On Tue, Jan 16, 2024 at 08:24:20AM +0100, Krzysztof Kozlowski wrote:
> > >> On 16/01/2024 03:29, Frank Li wrote:
> > >>>>> Patches were accepted after discussion, what you ponit to. So I
> > >>>>> think everyone agree on the name 'silvaco,i3c-master-v1'.
> > >>>>> I plan send next version to fix auto build error. Any additional
> > >>>>> comments about this?
> > >>>>
> > >>>> I still do not see how did you address Rob's comment and his point is
> > >>>> valid. You just did not reply to it.
> > >>>
> > >>> See https://lore.kernel.org/imx/ZXCiaKfMYYShoiXK@lizhi-Precision-Tower-5810/
> > >>
> > >> First of all, that's not the answer to Rob's email, but some other
> > >> thread which is 99% ignored by Rob (unless he has filters for
> > >> "@Rob"...). Therefore no, it does not count as valid answer.
> > >>
> > >> Second, explanation does not make sense. There is no argument granting
> > >> you exception from SoC specific compatibles.
> > >
> > > The patch could have been applied two months ago had Frank done as
> > > was requested (multiple times). I don't understand the resistance
> > > towards doing so given the process has taken way way longer as a result.
> >
> > I think that Rob's comment was just skipped and original master binding
> > was merged without addressing it. I don't want to repeat the same
> > process for the "target". Indeed I could point this earlier... if I only
> > knew that Rob pointed out that issue.
>
> Oh I think I got confused here. The context for this mail led me to
> think that this was still trying to push the i3c-master-v1 stuff through
> and I was commenting on my frustration with the resistance to applying
> the feedback received. I didn't realise that this was for another
> patch adding a target.
>
> I think you already said it, but NAK to adding any more compatibles here
> until the soc-specific compatible that was asked for for the imx93 is
> added.

Is it okay for 'silvaco,i3c-target-imx93'?

Frank

>
> Thanks,
> Conor.



2024-01-16 18:23:35

by Conor Dooley

[permalink] [raw]
Subject: Re: [PATCH v2 2/7] dt-bindings: i3c: svc: add compatible string i3c: silvaco,i3c-target-v1

On Tue, Jan 16, 2024 at 12:35:44PM -0500, Frank Li wrote:
> On Tue, Jan 16, 2024 at 09:48:08AM +0000, Conor Dooley wrote:
> > On Tue, Jan 16, 2024 at 10:33:48AM +0100, Krzysztof Kozlowski wrote:
> > > On 16/01/2024 10:30, Conor Dooley wrote:
> > > > On Tue, Jan 16, 2024 at 08:24:20AM +0100, Krzysztof Kozlowski wrote:
> > > >> On 16/01/2024 03:29, Frank Li wrote:
> > > >>>>> Patches were accepted after discussion, what you ponit to. So I
> > > >>>>> think everyone agree on the name 'silvaco,i3c-master-v1'.
> > > >>>>> I plan send next version to fix auto build error. Any additional
> > > >>>>> comments about this?
> > > >>>>
> > > >>>> I still do not see how did you address Rob's comment and his point is
> > > >>>> valid. You just did not reply to it.
> > > >>>
> > > >>> See https://lore.kernel.org/imx/ZXCiaKfMYYShoiXK@lizhi-Precision-Tower-5810/
> > > >>
> > > >> First of all, that's not the answer to Rob's email, but some other
> > > >> thread which is 99% ignored by Rob (unless he has filters for
> > > >> "@Rob"...). Therefore no, it does not count as valid answer.
> > > >>
> > > >> Second, explanation does not make sense. There is no argument granting
> > > >> you exception from SoC specific compatibles.
> > > >
> > > > The patch could have been applied two months ago had Frank done as
> > > > was requested (multiple times). I don't understand the resistance
> > > > towards doing so given the process has taken way way longer as a result.
> > >
> > > I think that Rob's comment was just skipped and original master binding
> > > was merged without addressing it. I don't want to repeat the same
> > > process for the "target". Indeed I could point this earlier... if I only
> > > knew that Rob pointed out that issue.
> >
> > Oh I think I got confused here. The context for this mail led me to
> > think that this was still trying to push the i3c-master-v1 stuff through
> > and I was commenting on my frustration with the resistance to applying
> > the feedback received. I didn't realise that this was for another
> > patch adding a target.
> >
> > I think you already said it, but NAK to adding any more compatibles here
> > until the soc-specific compatible that was asked for for the imx93 is
> > added.
>
> Is it okay for 'silvaco,i3c-target-imx93'?

I don't know. Is the device in question capable of also operating in
master mode? I have no idea from the commit message since it contains
zero information on the hardware.
If the exact same controller can operate in master and target mode,
having two compatibles for the same device does not seem okay to me.

Also, "silvaco" does not make the imx93 so that is not a suitable vendor
prefix. If the imx93 only supports i3c IPs in target mode, I would call
it "<vendorofimx>,imx93-i3c" with "silvaco,i3c-target-v1" as a fallback.

Thanks,
Conor.


Attachments:
(No filename) (2.82 kB)
signature.asc (235.00 B)
Download all attachments

2024-01-16 19:13:35

by Frank Li

[permalink] [raw]
Subject: Re: [PATCH v2 2/7] dt-bindings: i3c: svc: add compatible string i3c: silvaco,i3c-target-v1

On Tue, Jan 16, 2024 at 06:23:09PM +0000, Conor Dooley wrote:
> On Tue, Jan 16, 2024 at 12:35:44PM -0500, Frank Li wrote:
> > On Tue, Jan 16, 2024 at 09:48:08AM +0000, Conor Dooley wrote:
> > > On Tue, Jan 16, 2024 at 10:33:48AM +0100, Krzysztof Kozlowski wrote:
> > > > On 16/01/2024 10:30, Conor Dooley wrote:
> > > > > On Tue, Jan 16, 2024 at 08:24:20AM +0100, Krzysztof Kozlowski wrote:
> > > > >> On 16/01/2024 03:29, Frank Li wrote:
> > > > >>>>> Patches were accepted after discussion, what you ponit to. So I
> > > > >>>>> think everyone agree on the name 'silvaco,i3c-master-v1'.
> > > > >>>>> I plan send next version to fix auto build error. Any additional
> > > > >>>>> comments about this?
> > > > >>>>
> > > > >>>> I still do not see how did you address Rob's comment and his point is
> > > > >>>> valid. You just did not reply to it.
> > > > >>>
> > > > >>> See https://lore.kernel.org/imx/ZXCiaKfMYYShoiXK@lizhi-Precision-Tower-5810/
> > > > >>
> > > > >> First of all, that's not the answer to Rob's email, but some other
> > > > >> thread which is 99% ignored by Rob (unless he has filters for
> > > > >> "@Rob"...). Therefore no, it does not count as valid answer.
> > > > >>
> > > > >> Second, explanation does not make sense. There is no argument granting
> > > > >> you exception from SoC specific compatibles.
> > > > >
> > > > > The patch could have been applied two months ago had Frank done as
> > > > > was requested (multiple times). I don't understand the resistance
> > > > > towards doing so given the process has taken way way longer as a result.
> > > >
> > > > I think that Rob's comment was just skipped and original master binding
> > > > was merged without addressing it. I don't want to repeat the same
> > > > process for the "target". Indeed I could point this earlier... if I only
> > > > knew that Rob pointed out that issue.
> > >
> > > Oh I think I got confused here. The context for this mail led me to
> > > think that this was still trying to push the i3c-master-v1 stuff through
> > > and I was commenting on my frustration with the resistance to applying
> > > the feedback received. I didn't realise that this was for another
> > > patch adding a target.
> > >
> > > I think you already said it, but NAK to adding any more compatibles here
> > > until the soc-specific compatible that was asked for for the imx93 is
> > > added.
> >
> > Is it okay for 'silvaco,i3c-target-imx93'?
>
> I don't know. Is the device in question capable of also operating in
> master mode? I have no idea from the commit message since it contains
> zero information on the hardware.

Yes, it is dual mode controller.

> If the exact same controller can operate in master and target mode,
> having two compatibles for the same device does not seem okay to me.
>

what's your suggestion? create a total new yaml file for target mode (like
PCI ep)?
All target information(interrupt, reg, clock) are the same as master.

Or added "mode" property instead of using difference compatible string?
It may cause kconfig become complex to handle difference mode at the same
drivers.

> Also, "silvaco" does not make the imx93 so that is not a suitable vendor
> prefix. If the imx93 only supports i3c IPs in target mode, I would call
> it "<vendorofimx>,imx93-i3c" with "silvaco,i3c-target-v1" as a fallback.
>

Look like Rob and krysztof don't likes 'silvaco,i3c-target-v1'.

> Thanks,
> Conor.



2024-01-16 22:13:17

by Krzysztof Kozlowski

[permalink] [raw]
Subject: Re: [PATCH v2 2/7] dt-bindings: i3c: svc: add compatible string i3c: silvaco,i3c-target-v1

On 16/01/2024 20:13, Frank Li wrote:
> On Tue, Jan 16, 2024 at 06:23:09PM +0000, Conor Dooley wrote:
>> On Tue, Jan 16, 2024 at 12:35:44PM -0500, Frank Li wrote:
>>> On Tue, Jan 16, 2024 at 09:48:08AM +0000, Conor Dooley wrote:
>>>> On Tue, Jan 16, 2024 at 10:33:48AM +0100, Krzysztof Kozlowski wrote:
>>>>> On 16/01/2024 10:30, Conor Dooley wrote:
>>>>>> On Tue, Jan 16, 2024 at 08:24:20AM +0100, Krzysztof Kozlowski wrote:
>>>>>>> On 16/01/2024 03:29, Frank Li wrote:
>>>>>>>>>> Patches were accepted after discussion, what you ponit to. So I
>>>>>>>>>> think everyone agree on the name 'silvaco,i3c-master-v1'.
>>>>>>>>>> I plan send next version to fix auto build error. Any additional
>>>>>>>>>> comments about this?
>>>>>>>>>
>>>>>>>>> I still do not see how did you address Rob's comment and his point is
>>>>>>>>> valid. You just did not reply to it.
>>>>>>>>
>>>>>>>> See https://lore.kernel.org/imx/ZXCiaKfMYYShoiXK@lizhi-Precision-Tower-5810/
>>>>>>>
>>>>>>> First of all, that's not the answer to Rob's email, but some other
>>>>>>> thread which is 99% ignored by Rob (unless he has filters for
>>>>>>> "@Rob"...). Therefore no, it does not count as valid answer.
>>>>>>>
>>>>>>> Second, explanation does not make sense. There is no argument granting
>>>>>>> you exception from SoC specific compatibles.
>>>>>>
>>>>>> The patch could have been applied two months ago had Frank done as
>>>>>> was requested (multiple times). I don't understand the resistance
>>>>>> towards doing so given the process has taken way way longer as a result.
>>>>>
>>>>> I think that Rob's comment was just skipped and original master binding
>>>>> was merged without addressing it. I don't want to repeat the same
>>>>> process for the "target". Indeed I could point this earlier... if I only
>>>>> knew that Rob pointed out that issue.
>>>>
>>>> Oh I think I got confused here. The context for this mail led me to
>>>> think that this was still trying to push the i3c-master-v1 stuff through
>>>> and I was commenting on my frustration with the resistance to applying
>>>> the feedback received. I didn't realise that this was for another
>>>> patch adding a target.
>>>>
>>>> I think you already said it, but NAK to adding any more compatibles here
>>>> until the soc-specific compatible that was asked for for the imx93 is
>>>> added.
>>>
>>> Is it okay for 'silvaco,i3c-target-imx93'?

No, because imx93 is product of NXP, not Silvaco.

You need regular SoC-block compatibles, just like we have for all other
snps, dwc and cdns.


Best regards,
Krzysztof


2024-01-16 22:18:36

by Frank Li

[permalink] [raw]
Subject: Re: [PATCH v2 2/7] dt-bindings: i3c: svc: add compatible string i3c: silvaco,i3c-target-v1

On Tue, Jan 16, 2024 at 09:30:24PM +0100, Krzysztof Kozlowski wrote:
> On 16/01/2024 20:13, Frank Li wrote:
> > On Tue, Jan 16, 2024 at 06:23:09PM +0000, Conor Dooley wrote:
> >> On Tue, Jan 16, 2024 at 12:35:44PM -0500, Frank Li wrote:
> >>> On Tue, Jan 16, 2024 at 09:48:08AM +0000, Conor Dooley wrote:
> >>>> On Tue, Jan 16, 2024 at 10:33:48AM +0100, Krzysztof Kozlowski wrote:
> >>>>> On 16/01/2024 10:30, Conor Dooley wrote:
> >>>>>> On Tue, Jan 16, 2024 at 08:24:20AM +0100, Krzysztof Kozlowski wrote:
> >>>>>>> On 16/01/2024 03:29, Frank Li wrote:
> >>>>>>>>>> Patches were accepted after discussion, what you ponit to. So I
> >>>>>>>>>> think everyone agree on the name 'silvaco,i3c-master-v1'.
> >>>>>>>>>> I plan send next version to fix auto build error. Any additional
> >>>>>>>>>> comments about this?
> >>>>>>>>>
> >>>>>>>>> I still do not see how did you address Rob's comment and his point is
> >>>>>>>>> valid. You just did not reply to it.
> >>>>>>>>
> >>>>>>>> See https://lore.kernel.org/imx/ZXCiaKfMYYShoiXK@lizhi-Precision-Tower-5810/
> >>>>>>>
> >>>>>>> First of all, that's not the answer to Rob's email, but some other
> >>>>>>> thread which is 99% ignored by Rob (unless he has filters for
> >>>>>>> "@Rob"...). Therefore no, it does not count as valid answer.
> >>>>>>>
> >>>>>>> Second, explanation does not make sense. There is no argument granting
> >>>>>>> you exception from SoC specific compatibles.
> >>>>>>
> >>>>>> The patch could have been applied two months ago had Frank done as
> >>>>>> was requested (multiple times). I don't understand the resistance
> >>>>>> towards doing so given the process has taken way way longer as a result.
> >>>>>
> >>>>> I think that Rob's comment was just skipped and original master binding
> >>>>> was merged without addressing it. I don't want to repeat the same
> >>>>> process for the "target". Indeed I could point this earlier... if I only
> >>>>> knew that Rob pointed out that issue.
> >>>>
> >>>> Oh I think I got confused here. The context for this mail led me to
> >>>> think that this was still trying to push the i3c-master-v1 stuff through
> >>>> and I was commenting on my frustration with the resistance to applying
> >>>> the feedback received. I didn't realise that this was for another
> >>>> patch adding a target.
> >>>>
> >>>> I think you already said it, but NAK to adding any more compatibles here
> >>>> until the soc-specific compatible that was asked for for the imx93 is
> >>>> added.
> >>>
> >>> Is it okay for 'silvaco,i3c-target-imx93'?
>
> No, because imx93 is product of NXP, not Silvaco.
>
> You need regular SoC-block compatibles, just like we have for all other
> snps, dwc and cdns.

"nxp,imx93-svc-i3c-target" ? Just little bit strange for binding file name
is silvaco,i3c-master.yaml.

look like "dwc,*" compatitble string's file name is "dwc,*".yaml.

Frank
>
>
> Best regards,
> Krzysztof
>

2024-01-16 22:20:51

by Krzysztof Kozlowski

[permalink] [raw]
Subject: Re: [PATCH v2 2/7] dt-bindings: i3c: svc: add compatible string i3c: silvaco,i3c-target-v1

On 16/01/2024 21:56, Krzysztof Kozlowski wrote:
> On 16/01/2024 21:44, Frank Li wrote:
>> On Tue, Jan 16, 2024 at 09:30:24PM +0100, Krzysztof Kozlowski wrote:
>>> On 16/01/2024 20:13, Frank Li wrote:
>>>> On Tue, Jan 16, 2024 at 06:23:09PM +0000, Conor Dooley wrote:
>>>>> On Tue, Jan 16, 2024 at 12:35:44PM -0500, Frank Li wrote:
>>>>>> On Tue, Jan 16, 2024 at 09:48:08AM +0000, Conor Dooley wrote:
>>>>>>> On Tue, Jan 16, 2024 at 10:33:48AM +0100, Krzysztof Kozlowski wrote:
>>>>>>>> On 16/01/2024 10:30, Conor Dooley wrote:
>>>>>>>>> On Tue, Jan 16, 2024 at 08:24:20AM +0100, Krzysztof Kozlowski wrote:
>>>>>>>>>> On 16/01/2024 03:29, Frank Li wrote:
>>>>>>>>>>>>> Patches were accepted after discussion, what you ponit to. So I
>>>>>>>>>>>>> think everyone agree on the name 'silvaco,i3c-master-v1'.
>>>>>>>>>>>>> I plan send next version to fix auto build error. Any additional
>>>>>>>>>>>>> comments about this?
>>>>>>>>>>>>
>>>>>>>>>>>> I still do not see how did you address Rob's comment and his point is
>>>>>>>>>>>> valid. You just did not reply to it.
>>>>>>>>>>>
>>>>>>>>>>> See https://lore.kernel.org/imx/ZXCiaKfMYYShoiXK@lizhi-Precision-Tower-5810/
>>>>>>>>>>
>>>>>>>>>> First of all, that's not the answer to Rob's email, but some other
>>>>>>>>>> thread which is 99% ignored by Rob (unless he has filters for
>>>>>>>>>> "@Rob"...). Therefore no, it does not count as valid answer.
>>>>>>>>>>
>>>>>>>>>> Second, explanation does not make sense. There is no argument granting
>>>>>>>>>> you exception from SoC specific compatibles.
>>>>>>>>>
>>>>>>>>> The patch could have been applied two months ago had Frank done as
>>>>>>>>> was requested (multiple times). I don't understand the resistance
>>>>>>>>> towards doing so given the process has taken way way longer as a result.
>>>>>>>>
>>>>>>>> I think that Rob's comment was just skipped and original master binding
>>>>>>>> was merged without addressing it. I don't want to repeat the same
>>>>>>>> process for the "target". Indeed I could point this earlier... if I only
>>>>>>>> knew that Rob pointed out that issue.
>>>>>>>
>>>>>>> Oh I think I got confused here. The context for this mail led me to
>>>>>>> think that this was still trying to push the i3c-master-v1 stuff through
>>>>>>> and I was commenting on my frustration with the resistance to applying
>>>>>>> the feedback received. I didn't realise that this was for another
>>>>>>> patch adding a target.
>>>>>>>
>>>>>>> I think you already said it, but NAK to adding any more compatibles here
>>>>>>> until the soc-specific compatible that was asked for for the imx93 is
>>>>>>> added.
>>>>>>
>>>>>> Is it okay for 'silvaco,i3c-target-imx93'?
>>>
>>> No, because imx93 is product of NXP, not Silvaco.
>>>
>>> You need regular SoC-block compatibles, just like we have for all other
>>> snps, dwc and cdns.
>>
>> "nxp,imx93-svc-i3c-target" ?
>
> Could be, now please point me to patch adding such code to DTS. I would
> like to see the real use case for it.

Probably I was not clear enough, so let's be more precise: I think you
might have troubles pointing to such code, because it just does not
exist. It is a bit contradicting to single hardware description, because
you want to describe one hardware in two different ways, with two
different compatibles.

Your commit msg is here empty - it says what patch is does, which is
obvious. Tells nothing about the hardware being described here, which
does not help this discussion. This would need solving as well, but main
point stays - don't add new compatibles for the same hardware, at least
not without valid reason/explanation.

Best regards,
Krzysztof


2024-01-16 22:21:37

by Krzysztof Kozlowski

[permalink] [raw]
Subject: Re: [PATCH v2 2/7] dt-bindings: i3c: svc: add compatible string i3c: silvaco,i3c-target-v1

On 16/01/2024 21:44, Frank Li wrote:
> On Tue, Jan 16, 2024 at 09:30:24PM +0100, Krzysztof Kozlowski wrote:
>> On 16/01/2024 20:13, Frank Li wrote:
>>> On Tue, Jan 16, 2024 at 06:23:09PM +0000, Conor Dooley wrote:
>>>> On Tue, Jan 16, 2024 at 12:35:44PM -0500, Frank Li wrote:
>>>>> On Tue, Jan 16, 2024 at 09:48:08AM +0000, Conor Dooley wrote:
>>>>>> On Tue, Jan 16, 2024 at 10:33:48AM +0100, Krzysztof Kozlowski wrote:
>>>>>>> On 16/01/2024 10:30, Conor Dooley wrote:
>>>>>>>> On Tue, Jan 16, 2024 at 08:24:20AM +0100, Krzysztof Kozlowski wrote:
>>>>>>>>> On 16/01/2024 03:29, Frank Li wrote:
>>>>>>>>>>>> Patches were accepted after discussion, what you ponit to. So I
>>>>>>>>>>>> think everyone agree on the name 'silvaco,i3c-master-v1'.
>>>>>>>>>>>> I plan send next version to fix auto build error. Any additional
>>>>>>>>>>>> comments about this?
>>>>>>>>>>>
>>>>>>>>>>> I still do not see how did you address Rob's comment and his point is
>>>>>>>>>>> valid. You just did not reply to it.
>>>>>>>>>>
>>>>>>>>>> See https://lore.kernel.org/imx/ZXCiaKfMYYShoiXK@lizhi-Precision-Tower-5810/
>>>>>>>>>
>>>>>>>>> First of all, that's not the answer to Rob's email, but some other
>>>>>>>>> thread which is 99% ignored by Rob (unless he has filters for
>>>>>>>>> "@Rob"...). Therefore no, it does not count as valid answer.
>>>>>>>>>
>>>>>>>>> Second, explanation does not make sense. There is no argument granting
>>>>>>>>> you exception from SoC specific compatibles.
>>>>>>>>
>>>>>>>> The patch could have been applied two months ago had Frank done as
>>>>>>>> was requested (multiple times). I don't understand the resistance
>>>>>>>> towards doing so given the process has taken way way longer as a result.
>>>>>>>
>>>>>>> I think that Rob's comment was just skipped and original master binding
>>>>>>> was merged without addressing it. I don't want to repeat the same
>>>>>>> process for the "target". Indeed I could point this earlier... if I only
>>>>>>> knew that Rob pointed out that issue.
>>>>>>
>>>>>> Oh I think I got confused here. The context for this mail led me to
>>>>>> think that this was still trying to push the i3c-master-v1 stuff through
>>>>>> and I was commenting on my frustration with the resistance to applying
>>>>>> the feedback received. I didn't realise that this was for another
>>>>>> patch adding a target.
>>>>>>
>>>>>> I think you already said it, but NAK to adding any more compatibles here
>>>>>> until the soc-specific compatible that was asked for for the imx93 is
>>>>>> added.
>>>>>
>>>>> Is it okay for 'silvaco,i3c-target-imx93'?
>>
>> No, because imx93 is product of NXP, not Silvaco.
>>
>> You need regular SoC-block compatibles, just like we have for all other
>> snps, dwc and cdns.
>
> "nxp,imx93-svc-i3c-target" ?

Could be, now please point me to patch adding such code to DTS. I would
like to see the real use case for it.

> Just little bit strange for binding file name
> is silvaco,i3c-master.yaml.

Many other bindings do it. I don't see a problem in creating device
specific schema sharing some parts, if you have some common pieces.

>
> look like "dwc,*" compatitble string's file name is "dwc,*".yaml.

? I don't understand how is this related, but if this is what you want
to discuss then look:
Documentation/devicetree/bindings/usb/qcom,dwc3.yaml

or many other examples. Please open dwc, snps and cdns bindings and look
how it is done there.

Best regards,
Krzysztof


2024-01-16 22:28:54

by Frank Li

[permalink] [raw]
Subject: Re: [PATCH v2 2/7] dt-bindings: i3c: svc: add compatible string i3c: silvaco,i3c-target-v1

On Tue, Jan 16, 2024 at 09:56:03PM +0100, Krzysztof Kozlowski wrote:
> On 16/01/2024 21:44, Frank Li wrote:
> > On Tue, Jan 16, 2024 at 09:30:24PM +0100, Krzysztof Kozlowski wrote:
> >> On 16/01/2024 20:13, Frank Li wrote:
> >>> On Tue, Jan 16, 2024 at 06:23:09PM +0000, Conor Dooley wrote:
> >>>> On Tue, Jan 16, 2024 at 12:35:44PM -0500, Frank Li wrote:
> >>>>> On Tue, Jan 16, 2024 at 09:48:08AM +0000, Conor Dooley wrote:
> >>>>>> On Tue, Jan 16, 2024 at 10:33:48AM +0100, Krzysztof Kozlowski wrote:
> >>>>>>> On 16/01/2024 10:30, Conor Dooley wrote:
> >>>>>>>> On Tue, Jan 16, 2024 at 08:24:20AM +0100, Krzysztof Kozlowski wrote:
> >>>>>>>>> On 16/01/2024 03:29, Frank Li wrote:
> >>>>>>>>>>>> Patches were accepted after discussion, what you ponit to. So I
> >>>>>>>>>>>> think everyone agree on the name 'silvaco,i3c-master-v1'.
> >>>>>>>>>>>> I plan send next version to fix auto build error. Any additional
> >>>>>>>>>>>> comments about this?
> >>>>>>>>>>>
> >>>>>>>>>>> I still do not see how did you address Rob's comment and his point is
> >>>>>>>>>>> valid. You just did not reply to it.
> >>>>>>>>>>
> >>>>>>>>>> See https://lore.kernel.org/imx/ZXCiaKfMYYShoiXK@lizhi-Precision-Tower-5810/
> >>>>>>>>>
> >>>>>>>>> First of all, that's not the answer to Rob's email, but some other
> >>>>>>>>> thread which is 99% ignored by Rob (unless he has filters for
> >>>>>>>>> "@Rob"...). Therefore no, it does not count as valid answer.
> >>>>>>>>>
> >>>>>>>>> Second, explanation does not make sense. There is no argument granting
> >>>>>>>>> you exception from SoC specific compatibles.
> >>>>>>>>
> >>>>>>>> The patch could have been applied two months ago had Frank done as
> >>>>>>>> was requested (multiple times). I don't understand the resistance
> >>>>>>>> towards doing so given the process has taken way way longer as a result.
> >>>>>>>
> >>>>>>> I think that Rob's comment was just skipped and original master binding
> >>>>>>> was merged without addressing it. I don't want to repeat the same
> >>>>>>> process for the "target". Indeed I could point this earlier... if I only
> >>>>>>> knew that Rob pointed out that issue.
> >>>>>>
> >>>>>> Oh I think I got confused here. The context for this mail led me to
> >>>>>> think that this was still trying to push the i3c-master-v1 stuff through
> >>>>>> and I was commenting on my frustration with the resistance to applying
> >>>>>> the feedback received. I didn't realise that this was for another
> >>>>>> patch adding a target.
> >>>>>>
> >>>>>> I think you already said it, but NAK to adding any more compatibles here
> >>>>>> until the soc-specific compatible that was asked for for the imx93 is
> >>>>>> added.
> >>>>>
> >>>>> Is it okay for 'silvaco,i3c-target-imx93'?
> >>
> >> No, because imx93 is product of NXP, not Silvaco.
> >>
> >> You need regular SoC-block compatibles, just like we have for all other
> >> snps, dwc and cdns.
> >
> > "nxp,imx93-svc-i3c-target" ?
>
> Could be, now please point me to patch adding such code to DTS. I would
> like to see the real use case for it.

This part have not sent to review yet. basically in imx93evk.dts add

&i3c1 {
compatible = "silvaco,i3c-target-v1";
pinctrl-names = "default", "sleep";
pinctrl-0 = <&pinctrl_i3c1>;
pinctrl-1 = <&pinctrl_i3c1>;
status = "okay"
}

>
> > Just little bit strange for binding file name
> > is silvaco,i3c-master.yaml.
>
> Many other bindings do it. I don't see a problem in creating device
> specific schema sharing some parts, if you have some common pieces.
>
> >
> > look like "dwc,*" compatitble string's file name is "dwc,*".yaml.
>
> ? I don't understand how is this related, but if this is what you want
> to discuss then look:
> Documentation/devicetree/bindings/usb/qcom,dwc3.yaml
>
> or many other examples. Please open dwc, snps and cdns bindings and look
> how it is done there.
>
> Best regards,
> Krzysztof
>

2024-01-16 22:43:24

by Frank Li

[permalink] [raw]
Subject: Re: [PATCH v2 2/7] dt-bindings: i3c: svc: add compatible string i3c: silvaco,i3c-target-v1

On Tue, Jan 16, 2024 at 10:01:42PM +0100, Krzysztof Kozlowski wrote:
> On 16/01/2024 21:56, Krzysztof Kozlowski wrote:
> > On 16/01/2024 21:44, Frank Li wrote:
> >> On Tue, Jan 16, 2024 at 09:30:24PM +0100, Krzysztof Kozlowski wrote:
> >>> On 16/01/2024 20:13, Frank Li wrote:
> >>>> On Tue, Jan 16, 2024 at 06:23:09PM +0000, Conor Dooley wrote:
> >>>>> On Tue, Jan 16, 2024 at 12:35:44PM -0500, Frank Li wrote:
> >>>>>> On Tue, Jan 16, 2024 at 09:48:08AM +0000, Conor Dooley wrote:
> >>>>>>> On Tue, Jan 16, 2024 at 10:33:48AM +0100, Krzysztof Kozlowski wrote:
> >>>>>>>> On 16/01/2024 10:30, Conor Dooley wrote:
> >>>>>>>>> On Tue, Jan 16, 2024 at 08:24:20AM +0100, Krzysztof Kozlowski wrote:
> >>>>>>>>>> On 16/01/2024 03:29, Frank Li wrote:
> >>>>>>>>>>>>> Patches were accepted after discussion, what you ponit to. So I
> >>>>>>>>>>>>> think everyone agree on the name 'silvaco,i3c-master-v1'.
> >>>>>>>>>>>>> I plan send next version to fix auto build error. Any additional
> >>>>>>>>>>>>> comments about this?
> >>>>>>>>>>>>
> >>>>>>>>>>>> I still do not see how did you address Rob's comment and his point is
> >>>>>>>>>>>> valid. You just did not reply to it.
> >>>>>>>>>>>
> >>>>>>>>>>> See https://lore.kernel.org/imx/ZXCiaKfMYYShoiXK@lizhi-Precision-Tower-5810/
> >>>>>>>>>>
> >>>>>>>>>> First of all, that's not the answer to Rob's email, but some other
> >>>>>>>>>> thread which is 99% ignored by Rob (unless he has filters for
> >>>>>>>>>> "@Rob"...). Therefore no, it does not count as valid answer.
> >>>>>>>>>>
> >>>>>>>>>> Second, explanation does not make sense. There is no argument granting
> >>>>>>>>>> you exception from SoC specific compatibles.
> >>>>>>>>>
> >>>>>>>>> The patch could have been applied two months ago had Frank done as
> >>>>>>>>> was requested (multiple times). I don't understand the resistance
> >>>>>>>>> towards doing so given the process has taken way way longer as a result.
> >>>>>>>>
> >>>>>>>> I think that Rob's comment was just skipped and original master binding
> >>>>>>>> was merged without addressing it. I don't want to repeat the same
> >>>>>>>> process for the "target". Indeed I could point this earlier... if I only
> >>>>>>>> knew that Rob pointed out that issue.
> >>>>>>>
> >>>>>>> Oh I think I got confused here. The context for this mail led me to
> >>>>>>> think that this was still trying to push the i3c-master-v1 stuff through
> >>>>>>> and I was commenting on my frustration with the resistance to applying
> >>>>>>> the feedback received. I didn't realise that this was for another
> >>>>>>> patch adding a target.
> >>>>>>>
> >>>>>>> I think you already said it, but NAK to adding any more compatibles here
> >>>>>>> until the soc-specific compatible that was asked for for the imx93 is
> >>>>>>> added.
> >>>>>>
> >>>>>> Is it okay for 'silvaco,i3c-target-imx93'?
> >>>
> >>> No, because imx93 is product of NXP, not Silvaco.
> >>>
> >>> You need regular SoC-block compatibles, just like we have for all other
> >>> snps, dwc and cdns.
> >>
> >> "nxp,imx93-svc-i3c-target" ?
> >
> > Could be, now please point me to patch adding such code to DTS. I would
> > like to see the real use case for it.
>
> Probably I was not clear enough, so let's be more precise: I think you
> might have troubles pointing to such code, because it just does not
> exist. It is a bit contradicting to single hardware description, because
> you want to describe one hardware in two different ways, with two
> different compatibles.
>
> Your commit msg is here empty - it says what patch is does, which is
> obvious. Tells nothing about the hardware being described here, which
> does not help this discussion. This would need solving as well, but main
> point stays - don't add new compatibles for the same hardware, at least
> not without valid reason/explanation.

I can improve commt msg. It was similar PCI case (There are two work mode:
root complex and endpoint). So there are two kind compatible string for it.

If you think it is good for using two compatible string for two work mode
of the same hardware.

I can write git commit message like:

dt-bindings: i3c: svc: add compatible string nxp,imx93-svc-i3c-target

silvaco i3c controller is dual mode controller, which can work as master
and target mode. All clock, reg, irq are the same for both mode. Add
compatible string "nxp,imx93-svc-i3c-target" to let silivaco i3c
controller work as target mode.

Of course, alternate method to added a property "mode" to distingiush
master and target mode. but old "silvaco,i3c-master-v1" will actually work
as dual mode support. Driver structure will become complex.

Frank

>
> Best regards,
> Krzysztof
>

2024-01-17 06:45:31

by Krzysztof Kozlowski

[permalink] [raw]
Subject: Re: [PATCH v2 2/7] dt-bindings: i3c: svc: add compatible string i3c: silvaco,i3c-target-v1

On 16/01/2024 22:31, Frank Li wrote:

>>>>>>>
>>>>>>> Is it okay for 'silvaco,i3c-target-imx93'?
>>>>
>>>> No, because imx93 is product of NXP, not Silvaco.
>>>>
>>>> You need regular SoC-block compatibles, just like we have for all other
>>>> snps, dwc and cdns.
>>>
>>> "nxp,imx93-svc-i3c-target" ?
>>
>> Could be, now please point me to patch adding such code to DTS. I would
>> like to see the real use case for it.
>
> This part have not sent to review yet. basically in imx93evk.dts add
>
> &i3c1 {
> compatible = "silvaco,i3c-target-v1";
> pinctrl-names = "default", "sleep";
> pinctrl-0 = <&pinctrl_i3c1>;
> pinctrl-1 = <&pinctrl_i3c1>;
> status = "okay"
> }

Overriding compatible is not desired. It also supports here the
statement that this is the same hardware.

Best regards,
Krzysztof


2024-01-17 06:51:10

by Krzysztof Kozlowski

[permalink] [raw]
Subject: Re: [PATCH v2 2/7] dt-bindings: i3c: svc: add compatible string i3c: silvaco,i3c-target-v1

On 16/01/2024 23:25, Frank Li wrote:
> On Tue, Jan 16, 2024 at 10:01:42PM +0100, Krzysztof Kozlowski wrote:
>> On 16/01/2024 21:56, Krzysztof Kozlowski wrote:
>>> On 16/01/2024 21:44, Frank Li wrote:
>>>> On Tue, Jan 16, 2024 at 09:30:24PM +0100, Krzysztof Kozlowski wrote:
>>>>> On 16/01/2024 20:13, Frank Li wrote:
>>>>>> On Tue, Jan 16, 2024 at 06:23:09PM +0000, Conor Dooley wrote:
>>>>>>> On Tue, Jan 16, 2024 at 12:35:44PM -0500, Frank Li wrote:
>>>>>>>> On Tue, Jan 16, 2024 at 09:48:08AM +0000, Conor Dooley wrote:
>>>>>>>>> On Tue, Jan 16, 2024 at 10:33:48AM +0100, Krzysztof Kozlowski wrote:
>>>>>>>>>> On 16/01/2024 10:30, Conor Dooley wrote:
>>>>>>>>>>> On Tue, Jan 16, 2024 at 08:24:20AM +0100, Krzysztof Kozlowski wrote:
>>>>>>>>>>>> On 16/01/2024 03:29, Frank Li wrote:
>>>>>>>>>>>>>>> Patches were accepted after discussion, what you ponit to. So I
>>>>>>>>>>>>>>> think everyone agree on the name 'silvaco,i3c-master-v1'.
>>>>>>>>>>>>>>> I plan send next version to fix auto build error. Any additional
>>>>>>>>>>>>>>> comments about this?
>>>>>>>>>>>>>>
>>>>>>>>>>>>>> I still do not see how did you address Rob's comment and his point is
>>>>>>>>>>>>>> valid. You just did not reply to it.
>>>>>>>>>>>>>
>>>>>>>>>>>>> See https://lore.kernel.org/imx/ZXCiaKfMYYShoiXK@lizhi-Precision-Tower-5810/
>>>>>>>>>>>>
>>>>>>>>>>>> First of all, that's not the answer to Rob's email, but some other
>>>>>>>>>>>> thread which is 99% ignored by Rob (unless he has filters for
>>>>>>>>>>>> "@Rob"...). Therefore no, it does not count as valid answer.
>>>>>>>>>>>>
>>>>>>>>>>>> Second, explanation does not make sense. There is no argument granting
>>>>>>>>>>>> you exception from SoC specific compatibles.
>>>>>>>>>>>
>>>>>>>>>>> The patch could have been applied two months ago had Frank done as
>>>>>>>>>>> was requested (multiple times). I don't understand the resistance
>>>>>>>>>>> towards doing so given the process has taken way way longer as a result.
>>>>>>>>>>
>>>>>>>>>> I think that Rob's comment was just skipped and original master binding
>>>>>>>>>> was merged without addressing it. I don't want to repeat the same
>>>>>>>>>> process for the "target". Indeed I could point this earlier... if I only
>>>>>>>>>> knew that Rob pointed out that issue.
>>>>>>>>>
>>>>>>>>> Oh I think I got confused here. The context for this mail led me to
>>>>>>>>> think that this was still trying to push the i3c-master-v1 stuff through
>>>>>>>>> and I was commenting on my frustration with the resistance to applying
>>>>>>>>> the feedback received. I didn't realise that this was for another
>>>>>>>>> patch adding a target.
>>>>>>>>>
>>>>>>>>> I think you already said it, but NAK to adding any more compatibles here
>>>>>>>>> until the soc-specific compatible that was asked for for the imx93 is
>>>>>>>>> added.
>>>>>>>>
>>>>>>>> Is it okay for 'silvaco,i3c-target-imx93'?
>>>>>
>>>>> No, because imx93 is product of NXP, not Silvaco.
>>>>>
>>>>> You need regular SoC-block compatibles, just like we have for all other
>>>>> snps, dwc and cdns.
>>>>
>>>> "nxp,imx93-svc-i3c-target" ?
>>>
>>> Could be, now please point me to patch adding such code to DTS. I would
>>> like to see the real use case for it.
>>
>> Probably I was not clear enough, so let's be more precise: I think you
>> might have troubles pointing to such code, because it just does not
>> exist. It is a bit contradicting to single hardware description, because
>> you want to describe one hardware in two different ways, with two
>> different compatibles.
>>
>> Your commit msg is here empty - it says what patch is does, which is
>> obvious. Tells nothing about the hardware being described here, which
>> does not help this discussion. This would need solving as well, but main
>> point stays - don't add new compatibles for the same hardware, at least
>> not without valid reason/explanation.
>
> I can improve commt msg. It was similar PCI case (There are two work mode:
> root complex and endpoint). So there are two kind compatible string for it.
>
> If you think it is good for using two compatible string for two work mode
> of the same hardware.

Not really, because compatible describes hardware and it is the same
hardware here. We do not have two different compatibles for GPIOs being
input or output. Or two different compatibles for serial engines (ones
providing UART, SPI or I2C).

>
> I can write git commit message like:
>
> dt-bindings: i3c: svc: add compatible string nxp,imx93-svc-i3c-target
>
> silvaco i3c controller is dual mode controller, which can work as master
> and target mode. All clock, reg, irq are the same for both mode. Add
> compatible string "nxp,imx93-svc-i3c-target" to let silivaco i3c
> controller work as target mode.
>
> Of course, alternate method to added a property "mode" to distingiush
> master and target mode. but old "silvaco,i3c-master-v1" will actually work
> as dual mode support. Driver structure will become complex.

Please send full DTS of user for this, which works for 100%, so we can
see how it differs from controller mode. If your code snippet from other
thread is correct, then it would suggest "mode" property or lack of
children. Maybe lack of children is not enough, if user-space could
control I3C bus.

Best regards,
Krzysztof


2024-01-17 16:20:05

by Frank Li

[permalink] [raw]
Subject: Re: [PATCH v2 2/7] dt-bindings: i3c: svc: add compatible string i3c: silvaco,i3c-target-v1

On Wed, Jan 17, 2024 at 07:50:16AM +0100, Krzysztof Kozlowski wrote:
> On 16/01/2024 23:25, Frank Li wrote:
> > On Tue, Jan 16, 2024 at 10:01:42PM +0100, Krzysztof Kozlowski wrote:
> >> On 16/01/2024 21:56, Krzysztof Kozlowski wrote:
> >>> On 16/01/2024 21:44, Frank Li wrote:
> >>>> On Tue, Jan 16, 2024 at 09:30:24PM +0100, Krzysztof Kozlowski wrote:
> >>>>> On 16/01/2024 20:13, Frank Li wrote:
> >>>>>> On Tue, Jan 16, 2024 at 06:23:09PM +0000, Conor Dooley wrote:
> >>>>>>> On Tue, Jan 16, 2024 at 12:35:44PM -0500, Frank Li wrote:
> >>>>>>>> On Tue, Jan 16, 2024 at 09:48:08AM +0000, Conor Dooley wrote:
> >>>>>>>>> On Tue, Jan 16, 2024 at 10:33:48AM +0100, Krzysztof Kozlowski wrote:
> >>>>>>>>>> On 16/01/2024 10:30, Conor Dooley wrote:
> >>>>>>>>>>> On Tue, Jan 16, 2024 at 08:24:20AM +0100, Krzysztof Kozlowski wrote:
> >>>>>>>>>>>> On 16/01/2024 03:29, Frank Li wrote:
> >>>>>>>>>>>>>>> Patches were accepted after discussion, what you ponit to. So I
> >>>>>>>>>>>>>>> think everyone agree on the name 'silvaco,i3c-master-v1'.
> >>>>>>>>>>>>>>> I plan send next version to fix auto build error. Any additional
> >>>>>>>>>>>>>>> comments about this?
> >>>>>>>>>>>>>>
> >>>>>>>>>>>>>> I still do not see how did you address Rob's comment and his point is
> >>>>>>>>>>>>>> valid. You just did not reply to it.
> >>>>>>>>>>>>>
> >>>>>>>>>>>>> See https://lore.kernel.org/imx/ZXCiaKfMYYShoiXK@lizhi-Precision-Tower-5810/
> >>>>>>>>>>>>
> >>>>>>>>>>>> First of all, that's not the answer to Rob's email, but some other
> >>>>>>>>>>>> thread which is 99% ignored by Rob (unless he has filters for
> >>>>>>>>>>>> "@Rob"...). Therefore no, it does not count as valid answer.
> >>>>>>>>>>>>
> >>>>>>>>>>>> Second, explanation does not make sense. There is no argument granting
> >>>>>>>>>>>> you exception from SoC specific compatibles.
> >>>>>>>>>>>
> >>>>>>>>>>> The patch could have been applied two months ago had Frank done as
> >>>>>>>>>>> was requested (multiple times). I don't understand the resistance
> >>>>>>>>>>> towards doing so given the process has taken way way longer as a result.
> >>>>>>>>>>
> >>>>>>>>>> I think that Rob's comment was just skipped and original master binding
> >>>>>>>>>> was merged without addressing it. I don't want to repeat the same
> >>>>>>>>>> process for the "target". Indeed I could point this earlier... if I only
> >>>>>>>>>> knew that Rob pointed out that issue.
> >>>>>>>>>
> >>>>>>>>> Oh I think I got confused here. The context for this mail led me to
> >>>>>>>>> think that this was still trying to push the i3c-master-v1 stuff through
> >>>>>>>>> and I was commenting on my frustration with the resistance to applying
> >>>>>>>>> the feedback received. I didn't realise that this was for another
> >>>>>>>>> patch adding a target.
> >>>>>>>>>
> >>>>>>>>> I think you already said it, but NAK to adding any more compatibles here
> >>>>>>>>> until the soc-specific compatible that was asked for for the imx93 is
> >>>>>>>>> added.
> >>>>>>>>
> >>>>>>>> Is it okay for 'silvaco,i3c-target-imx93'?
> >>>>>
> >>>>> No, because imx93 is product of NXP, not Silvaco.
> >>>>>
> >>>>> You need regular SoC-block compatibles, just like we have for all other
> >>>>> snps, dwc and cdns.
> >>>>
> >>>> "nxp,imx93-svc-i3c-target" ?
> >>>
> >>> Could be, now please point me to patch adding such code to DTS. I would
> >>> like to see the real use case for it.
> >>
> >> Probably I was not clear enough, so let's be more precise: I think you
> >> might have troubles pointing to such code, because it just does not
> >> exist. It is a bit contradicting to single hardware description, because
> >> you want to describe one hardware in two different ways, with two
> >> different compatibles.
> >>
> >> Your commit msg is here empty - it says what patch is does, which is
> >> obvious. Tells nothing about the hardware being described here, which
> >> does not help this discussion. This would need solving as well, but main
> >> point stays - don't add new compatibles for the same hardware, at least
> >> not without valid reason/explanation.
> >
> > I can improve commt msg. It was similar PCI case (There are two work mode:
> > root complex and endpoint). So there are two kind compatible string for it.
> >
> > If you think it is good for using two compatible string for two work mode
> > of the same hardware.
>
> Not really, because compatible describes hardware and it is the same
> hardware here. We do not have two different compatibles for GPIOs being
> input or output. Or two different compatibles for serial engines (ones
> providing UART, SPI or I2C).

GPIO and UART is simple. Actuall SPI and I2C have two mode, slave and
master. Many SPI/I2C is dual mode controller. Just seldom use slave mode
at linux side. So you just see master mode SPI/I2C controller in dt-binding
and dts file. So few people upstream slave part to linux kernel community.
They have the exact same problems if support slave mode.

PCI is typical example:
EP mode: Documentation/devicetree/bindings/pci/qcom,pcie-ep.yaml
RC mode: Documentation/devicetree/bindings/pci/qcom,pcie.yaml

Which is the same hardware for two difference compatible string.
>
> >
> > I can write git commit message like:
> >
> > dt-bindings: i3c: svc: add compatible string nxp,imx93-svc-i3c-target
> >
> > silvaco i3c controller is dual mode controller, which can work as master
> > and target mode. All clock, reg, irq are the same for both mode. Add
> > compatible string "nxp,imx93-svc-i3c-target" to let silivaco i3c
> > controller work as target mode.
> >
> > Of course, alternate method to added a property "mode" to distingiush
> > master and target mode. but old "silvaco,i3c-master-v1" will actually work
> > as dual mode support. Driver structure will become complex.
>
> Please send full DTS of user for this, which works for 100%, so we can
> see how it differs from controller mode. If your code snippet from other
> thread is correct, then it would suggest "mode" property or lack of
> children. Maybe lack of children is not enough, if user-space could
> control I3C bus.

According to current implment, only need change imx93.dtsi's @i3c1's
compatible string to "silvaco,i3c-target-v1". I attached imx93 dts node for
your reference.

i3c1: i3c-master@44330000 {
compatible = "silvaco,i3c-master-v1";
^^^^ only need change here!

reg = <0x44330000 0x10000>;
interrupts = <GIC_SPI 12 IRQ_TYPE_LEVEL_HIGH>;
#address-cells = <3>;
#size-cells = <0>;
clocks = <&clk IMX93_CLK_BUS_AON>,
<&clk IMX93_CLK_I3C1_GATE>,
<&clk IMX93_CLK_I3C1_SLOW>;
clock-names = "pclk", "fast_clk", "slow_clk";
dmas = <&edma1 6 0 1>, <&edma1 5 0 0>;
dma-names = "rx", "tx";
status = "disabled";
};

For master mode:
Unlike i2c. Genenally I3C can auto probe children node like USB can auto
detect attached devices. So I3C master can work without children nodes.
Such as auto load i3c sensor driver according to i3c standard vendor id and
production id.

For target mode: using configfs to controller I3C.

mkdir /sys/kernel/config/i3c_target/functions/tty/t
echo 0x011b > /sys/kernel/config/i3c_target/functions/tty/t/vendor_id
echo 0x1000 > /sys/kernel/config/i3c_target/functions/tty/t/part_id
echo 0x6 > /sys/kernel/config/i3c_target/functions/tty/t/bcr

ln -s /sys/kernel/config/i3c_target/functions/tty/t /sys/kernel/config/i3c_target/controllers/44330000.i3c-master/

Then you echo test >/dev/ttySI3C0.

Unlike USB, user can switch host and gadget mode dymatically. Suppose I3C
only work on one of master or slave mode only, which is static.

Although it is one hardware, I think it is exculsive multi function device.

Summary: basice two option to distingiush controller and target mode.
1. by "compatible" string
2. by "mode"

I think 1 is relatively simple and easy to understand.

>
> Best regards,
> Krzysztof
>

2024-01-17 17:16:09

by Krzysztof Kozlowski

[permalink] [raw]
Subject: Re: [PATCH v2 2/7] dt-bindings: i3c: svc: add compatible string i3c: silvaco,i3c-target-v1

On 17/01/2024 17:19, Frank Li wrote:
>>
>> Not really, because compatible describes hardware and it is the same
>> hardware here. We do not have two different compatibles for GPIOs being
>> input or output. Or two different compatibles for serial engines (ones
>> providing UART, SPI or I2C).
>
> GPIO and UART is simple. Actuall SPI and I2C have two mode, slave and

I talked about serial engines which can be multiple: UART, SPI and I2C.

> master. Many SPI/I2C is dual mode controller. Just seldom use slave mode
> at linux side. So you just see master mode SPI/I2C controller in dt-binding
> and dts file. So few people upstream slave part to linux kernel community.
> They have the exact same problems if support slave mode.
>
> PCI is typical example:
> EP mode: Documentation/devicetree/bindings/pci/qcom,pcie-ep.yaml
> RC mode: Documentation/devicetree/bindings/pci/qcom,pcie.yaml
>
> Which is the same hardware for two difference compatible string.

That's the only case, I recall.

>>
>>>
>>> I can write git commit message like:
>>>
>>> dt-bindings: i3c: svc: add compatible string nxp,imx93-svc-i3c-target
>>>
>>> silvaco i3c controller is dual mode controller, which can work as master
>>> and target mode. All clock, reg, irq are the same for both mode. Add
>>> compatible string "nxp,imx93-svc-i3c-target" to let silivaco i3c
>>> controller work as target mode.
>>>
>>> Of course, alternate method to added a property "mode" to distingiush
>>> master and target mode. but old "silvaco,i3c-master-v1" will actually work
>>> as dual mode support. Driver structure will become complex.
>>
>> Please send full DTS of user for this, which works for 100%, so we can
>> see how it differs from controller mode. If your code snippet from other
>> thread is correct, then it would suggest "mode" property or lack of
>> children. Maybe lack of children is not enough, if user-space could
>> control I3C bus.
>
> According to current implment, only need change imx93.dtsi's @i3c1's
> compatible string to "silvaco,i3c-target-v1". I attached imx93 dts node for
> your reference.
>
> i3c1: i3c-master@44330000 {
> compatible = "silvaco,i3c-master-v1";
> ^^^^ only need change here!

Nope, don't change compatibles of existing nodes. Unreadable and
unmanageable code.

>
> reg = <0x44330000 0x10000>;
> interrupts = <GIC_SPI 12 IRQ_TYPE_LEVEL_HIGH>;
> #address-cells = <3>;
> #size-cells = <0>;
> clocks = <&clk IMX93_CLK_BUS_AON>,
> <&clk IMX93_CLK_I3C1_GATE>,
> <&clk IMX93_CLK_I3C1_SLOW>;
> clock-names = "pclk", "fast_clk", "slow_clk";
> dmas = <&edma1 6 0 1>, <&edma1 5 0 0>;
> dma-names = "rx", "tx";
> status = "disabled";
> };

That's not a patch for existing file. I did not claim you cannot write
such DTS. I claimed you don't have such DTS for upstream...

>
> For master mode:
> Unlike i2c. Genenally I3C can auto probe children node like USB can auto
> detect attached devices. So I3C master can work without children nodes.
> Such as auto load i3c sensor driver according to i3c standard vendor id and
> production id.

Then presence of children cannot be used.

>
> For target mode: using configfs to controller I3C.
>
> mkdir /sys/kernel/config/i3c_target/functions/tty/t
> echo 0x011b > /sys/kernel/config/i3c_target/functions/tty/t/vendor_id
> echo 0x1000 > /sys/kernel/config/i3c_target/functions/tty/t/part_id
> echo 0x6 > /sys/kernel/config/i3c_target/functions/tty/t/bcr
>
> ln -s /sys/kernel/config/i3c_target/functions/tty/t /sys/kernel/config/i3c_target/controllers/44330000.i3c-master/
>
> Then you echo test >/dev/ttySI3C0.
>
> Unlike USB, user can switch host and gadget mode dymatically. Suppose I3C
> only work on one of master or slave mode only, which is static.

I don't understand this. So it can switch dynamically or not?

>
> Although it is one hardware, I think it is exculsive multi function device.

Just like serial engines. Do you see there replacing compatibles? No.

>
> Summary: basice two option to distingiush controller and target mode.
> 1. by "compatible" string
> 2. by "mode"
>
> I think 1 is relatively simple and easy to understand.

Eh, if you only saw my comments on people replacing compatibles...
Anyway, I stated my reasons, so to reiterate: NAK.

Best regards,
Krzysztof


2024-01-17 18:07:54

by Frank Li

[permalink] [raw]
Subject: Re: [PATCH v2 2/7] dt-bindings: i3c: svc: add compatible string i3c: silvaco,i3c-target-v1

On Wed, Jan 17, 2024 at 06:15:51PM +0100, Krzysztof Kozlowski wrote:
> On 17/01/2024 17:19, Frank Li wrote:
> >>
> >> Not really, because compatible describes hardware and it is the same
> >> hardware here. We do not have two different compatibles for GPIOs being
> >> input or output. Or two different compatibles for serial engines (ones
> >> providing UART, SPI or I2C).
> >
> > GPIO and UART is simple. Actuall SPI and I2C have two mode, slave and
>
> I talked about serial engines which can be multiple: UART, SPI and I2C.
>
> > master. Many SPI/I2C is dual mode controller. Just seldom use slave mode
> > at linux side. So you just see master mode SPI/I2C controller in dt-binding
> > and dts file. So few people upstream slave part to linux kernel community.
> > They have the exact same problems if support slave mode.
> >
> > PCI is typical example:
> > EP mode: Documentation/devicetree/bindings/pci/qcom,pcie-ep.yaml
> > RC mode: Documentation/devicetree/bindings/pci/qcom,pcie.yaml
> >
> > Which is the same hardware for two difference compatible string.
>
> That's the only case, I recall.

As my knowledge, yes.

>
> >>
> >>>
> >>> I can write git commit message like:
> >>>
> >>> dt-bindings: i3c: svc: add compatible string nxp,imx93-svc-i3c-target
> >>>
> >>> silvaco i3c controller is dual mode controller, which can work as master
> >>> and target mode. All clock, reg, irq are the same for both mode. Add
> >>> compatible string "nxp,imx93-svc-i3c-target" to let silivaco i3c
> >>> controller work as target mode.
> >>>
> >>> Of course, alternate method to added a property "mode" to distingiush
> >>> master and target mode. but old "silvaco,i3c-master-v1" will actually work
> >>> as dual mode support. Driver structure will become complex.
> >>
> >> Please send full DTS of user for this, which works for 100%, so we can
> >> see how it differs from controller mode. If your code snippet from other
> >> thread is correct, then it would suggest "mode" property or lack of
> >> children. Maybe lack of children is not enough, if user-space could
> >> control I3C bus.
> >
> > According to current implment, only need change imx93.dtsi's @i3c1's
> > compatible string to "silvaco,i3c-target-v1". I attached imx93 dts node for
> > your reference.
> >
> > i3c1: i3c-master@44330000 {
> > compatible = "silvaco,i3c-master-v1";
> > ^^^^ only need change here!
>
> Nope, don't change compatibles of existing nodes. Unreadable and
> unmanageable code.

It is just show minimize difference.

Normally, it should be.

i3c1: i3c-master@44330000 {
...
compatible = "silvaco,i3c-master-v1";
...
status = disabled;
}

i3c1-target: i3c-target@44330000 {
...
compatible = "silvaco,i3c-target-v1";
...
status = disabled;
}

in board dts

@i3c1{
status = "okay";
}

Or
@i3c1-target{
status = "okay";
}
>
> >
> > reg = <0x44330000 0x10000>;
> > interrupts = <GIC_SPI 12 IRQ_TYPE_LEVEL_HIGH>;
> > #address-cells = <3>;
> > #size-cells = <0>;
> > clocks = <&clk IMX93_CLK_BUS_AON>,
> > <&clk IMX93_CLK_I3C1_GATE>,
> > <&clk IMX93_CLK_I3C1_SLOW>;
> > clock-names = "pclk", "fast_clk", "slow_clk";
> > dmas = <&edma1 6 0 1>, <&edma1 5 0 0>;
> > dma-names = "rx", "tx";
> > status = "disabled";
> > };
>
> That's not a patch for existing file. I did not claim you cannot write
> such DTS. I claimed you don't have such DTS for upstream...

Yes, it need finialize this topic before handle dts upstream.

>
> >
> > For master mode:
> > Unlike i2c. Genenally I3C can auto probe children node like USB can auto
> > detect attached devices. So I3C master can work without children nodes.
> > Such as auto load i3c sensor driver according to i3c standard vendor id and
> > production id.
>
> Then presence of children cannot be used.
>
> >
> > For target mode: using configfs to controller I3C.
> >
> > mkdir /sys/kernel/config/i3c_target/functions/tty/t
> > echo 0x011b > /sys/kernel/config/i3c_target/functions/tty/t/vendor_id
> > echo 0x1000 > /sys/kernel/config/i3c_target/functions/tty/t/part_id
> > echo 0x6 > /sys/kernel/config/i3c_target/functions/tty/t/bcr
> >
> > ln -s /sys/kernel/config/i3c_target/functions/tty/t /sys/kernel/config/i3c_target/controllers/44330000.i3c-master/
> >
> > Then you echo test >/dev/ttySI3C0.
> >
> > Unlike USB, user can switch host and gadget mode dymatically. Suppose I3C
> > only work on one of master or slave mode only, which is static.
>
> I don't understand this. So it can switch dynamically or not?

I3C Protocal allow do that. But no one really do that.

>
> >
> > Although it is one hardware, I think it is exculsive multi function device.
>
> Just like serial engines. Do you see there replacing compatibles? No.
>
> >
> > Summary: basice two option to distingiush controller and target mode.
> > 1. by "compatible" string
> > 2. by "mode"
> >
> > I think 1 is relatively simple and easy to understand.
>
> Eh, if you only saw my comments on people replacing compatibles...
> Anyway, I stated my reasons, so to reiterate: NAK.

I know it. Needn't emphase it every time.

Is using "mode" ('controller' and 'target') proptery okay?

Frank

>
> Best regards,
> Krzysztof
>

2024-01-19 17:17:48

by Frank Li

[permalink] [raw]
Subject: Re: [PATCH v2 2/7] dt-bindings: i3c: svc: add compatible string i3c: silvaco,i3c-target-v1

On Wed, Jan 17, 2024 at 01:06:15PM -0500, Frank Li wrote:
> On Wed, Jan 17, 2024 at 06:15:51PM +0100, Krzysztof Kozlowski wrote:
> > On 17/01/2024 17:19, Frank Li wrote:
> > >>
> > >> Not really, because compatible describes hardware and it is the same
> > >> hardware here. We do not have two different compatibles for GPIOs being
> > >> input or output. Or two different compatibles for serial engines (ones
> > >> providing UART, SPI or I2C).
> > >
> > > GPIO and UART is simple. Actuall SPI and I2C have two mode, slave and
> >
> > I talked about serial engines which can be multiple: UART, SPI and I2C.
> >
> > > master. Many SPI/I2C is dual mode controller. Just seldom use slave mode
> > > at linux side. So you just see master mode SPI/I2C controller in dt-binding
> > > and dts file. So few people upstream slave part to linux kernel community.
> > > They have the exact same problems if support slave mode.
> > >
> > > PCI is typical example:
> > > EP mode: Documentation/devicetree/bindings/pci/qcom,pcie-ep.yaml
> > > RC mode: Documentation/devicetree/bindings/pci/qcom,pcie.yaml
> > >
> > > Which is the same hardware for two difference compatible string.
> >
> > That's the only case, I recall.
>
> As my knowledge, yes.
>
> >
> > >>
> > >>>
> > >>> I can write git commit message like:
> > >>>
> > >>> dt-bindings: i3c: svc: add compatible string nxp,imx93-svc-i3c-target
> > >>>
> > >>> silvaco i3c controller is dual mode controller, which can work as master
> > >>> and target mode. All clock, reg, irq are the same for both mode. Add
> > >>> compatible string "nxp,imx93-svc-i3c-target" to let silivaco i3c
> > >>> controller work as target mode.
> > >>>
> > >>> Of course, alternate method to added a property "mode" to distingiush
> > >>> master and target mode. but old "silvaco,i3c-master-v1" will actually work
> > >>> as dual mode support. Driver structure will become complex.
> > >>
> > >> Please send full DTS of user for this, which works for 100%, so we can
> > >> see how it differs from controller mode. If your code snippet from other
> > >> thread is correct, then it would suggest "mode" property or lack of
> > >> children. Maybe lack of children is not enough, if user-space could
> > >> control I3C bus.
> > >
> > > According to current implment, only need change imx93.dtsi's @i3c1's
> > > compatible string to "silvaco,i3c-target-v1". I attached imx93 dts node for
> > > your reference.
> > >
> > > i3c1: i3c-master@44330000 {
> > > compatible = "silvaco,i3c-master-v1";
> > > ^^^^ only need change here!
> >
> > Nope, don't change compatibles of existing nodes. Unreadable and
> > unmanageable code.
>
> It is just show minimize difference.
>
> Normally, it should be.
>
> i3c1: i3c-master@44330000 {
> ...
> compatible = "silvaco,i3c-master-v1";
> ...
> status = disabled;
> }
>
> i3c1-target: i3c-target@44330000 {
> ...
> compatible = "silvaco,i3c-target-v1";
> ...
> status = disabled;
> }
>
> in board dts
>
> @i3c1{
> status = "okay";
> }
>
> Or
> @i3c1-target{
> status = "okay";
> }
> >
> > >
> > > reg = <0x44330000 0x10000>;
> > > interrupts = <GIC_SPI 12 IRQ_TYPE_LEVEL_HIGH>;
> > > #address-cells = <3>;
> > > #size-cells = <0>;
> > > clocks = <&clk IMX93_CLK_BUS_AON>,
> > > <&clk IMX93_CLK_I3C1_GATE>,
> > > <&clk IMX93_CLK_I3C1_SLOW>;
> > > clock-names = "pclk", "fast_clk", "slow_clk";
> > > dmas = <&edma1 6 0 1>, <&edma1 5 0 0>;
> > > dma-names = "rx", "tx";
> > > status = "disabled";
> > > };
> >
> > That's not a patch for existing file. I did not claim you cannot write
> > such DTS. I claimed you don't have such DTS for upstream...
>
> Yes, it need finialize this topic before handle dts upstream.
>
> >
> > >
> > > For master mode:
> > > Unlike i2c. Genenally I3C can auto probe children node like USB can auto
> > > detect attached devices. So I3C master can work without children nodes.
> > > Such as auto load i3c sensor driver according to i3c standard vendor id and
> > > production id.
> >
> > Then presence of children cannot be used.
> >
> > >
> > > For target mode: using configfs to controller I3C.
> > >
> > > mkdir /sys/kernel/config/i3c_target/functions/tty/t
> > > echo 0x011b > /sys/kernel/config/i3c_target/functions/tty/t/vendor_id
> > > echo 0x1000 > /sys/kernel/config/i3c_target/functions/tty/t/part_id
> > > echo 0x6 > /sys/kernel/config/i3c_target/functions/tty/t/bcr
> > >
> > > ln -s /sys/kernel/config/i3c_target/functions/tty/t /sys/kernel/config/i3c_target/controllers/44330000.i3c-master/
> > >
> > > Then you echo test >/dev/ttySI3C0.
> > >
> > > Unlike USB, user can switch host and gadget mode dymatically. Suppose I3C
> > > only work on one of master or slave mode only, which is static.
> >
> > I don't understand this. So it can switch dynamically or not?
>
> I3C Protocal allow do that. But no one really do that.
>
> >
> > >
> > > Although it is one hardware, I think it is exculsive multi function device.
> >
> > Just like serial engines. Do you see there replacing compatibles? No.
> >
> > >
> > > Summary: basice two option to distingiush controller and target mode.
> > > 1. by "compatible" string
> > > 2. by "mode"
> > >
> > > I think 1 is relatively simple and easy to understand.
> >
> > Eh, if you only saw my comments on people replacing compatibles...
> > Anyway, I stated my reasons, so to reiterate: NAK.
>
> I know it. Needn't emphase it every time.
>
> Is using "mode" ('controller' and 'target') proptery okay?

@krzyszkof:
Do you agree using "mode"?

Frank
>
> Frank
>
> >
> > Best regards,
> > Krzysztof
> >