* Re: [PATCH v9 3/7] i3c: master: add i3c_secondary_master_register
@ 2020-11-29 17:38 kernel test robot
0 siblings, 0 replies; 5+ messages in thread
From: kernel test robot @ 2020-11-29 17:38 UTC (permalink / raw)
To: kbuild
[-- Attachment #1: Type: text/plain, Size: 8674 bytes --]
CC: kbuild-all(a)lists.01.org
In-Reply-To: <1606659765-19490-1-git-send-email-pthombar@cadence.com>
References: <1606659765-19490-1-git-send-email-pthombar@cadence.com>
TO: Parshuram Thombare <pthombar@cadence.com>
TO: alexandre.belloni(a)bootlin.com
TO: slongerbeam(a)gmail.com
TO: vitor.soares(a)synopsys.com
CC: linux-i3c(a)lists.infradead.org
CC: linux-kernel(a)vger.kernel.org
CC: mparab(a)cadence.com
CC: praneeth(a)ti.com
CC: Parshuram Thombare <pthombar@cadence.com>
Hi Parshuram,
Thank you for the patch! Perhaps something to improve:
[auto build test WARNING on next-20201127]
[cannot apply to linus/master v5.10-rc5 v5.10-rc4 v5.10-rc3 v5.10-rc5]
[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]
url: https://github.com/0day-ci/linux/commits/Parshuram-Thombare/I3C-mastership-handover-support/20201129-222847
base: 6174f05255e65622ff3340257879a4c0f858b0df
:::::: branch date: 3 hours ago
:::::: commit date: 3 hours ago
config: i386-randconfig-m021-20201129 (attached as .config)
compiler: gcc-9 (Debian 9.3.0-15) 9.3.0
If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>
Reported-by: Dan Carpenter <dan.carpenter@oracle.com>
New smatch warnings:
drivers/i3c/master.c:1842 i3c_secondary_master_bus_init() warn: passing a valid pointer to 'PTR_ERR'
Old smatch warnings:
drivers/i3c/master.c:462 mode_show() warn: unsigned 'i3cbus->mode' is never less than zero.
drivers/i3c/master.c:1594 i3c_master_set_info() warn: passing a valid pointer to 'PTR_ERR'
drivers/i3c/master.c:1697 i3c_primary_master_bus_init() warn: passing a valid pointer to 'PTR_ERR'
drivers/i3c/master.c:1952 i3c_master_add_i3c_dev_locked() warn: passing a valid pointer to 'PTR_ERR'
vim +/PTR_ERR +1842 drivers/i3c/master.c
3a379bbcea0af6 Boris Brezillon 2017-07-19 1799
5386a14513be24 Parshuram Thombare 2020-11-29 1800 /**
5386a14513be24 Parshuram Thombare 2020-11-29 1801 * i3c_secondary_master_bus_init() - initialize an I3C bus for secondary
5386a14513be24 Parshuram Thombare 2020-11-29 1802 * master
5386a14513be24 Parshuram Thombare 2020-11-29 1803 * @master: secondary master initializing the bus
5386a14513be24 Parshuram Thombare 2020-11-29 1804 *
5386a14513be24 Parshuram Thombare 2020-11-29 1805 * This function does
5386a14513be24 Parshuram Thombare 2020-11-29 1806 *
5386a14513be24 Parshuram Thombare 2020-11-29 1807 * 1. Attach I2C devs to the master
5386a14513be24 Parshuram Thombare 2020-11-29 1808 *
5386a14513be24 Parshuram Thombare 2020-11-29 1809 * 2. Call &i3c_master_controller_ops->bus_init() method to initialize
5386a14513be24 Parshuram Thombare 2020-11-29 1810 * the master controller. That's usually where the bus mode is selected
5386a14513be24 Parshuram Thombare 2020-11-29 1811 * (pure bus or mixed fast/slow bus)
5386a14513be24 Parshuram Thombare 2020-11-29 1812 *
5386a14513be24 Parshuram Thombare 2020-11-29 1813 * Once this is done, I2C devices should be usable.
5386a14513be24 Parshuram Thombare 2020-11-29 1814 *
5386a14513be24 Parshuram Thombare 2020-11-29 1815 * Return: a 0 in case of success, an negative error code otherwise.
5386a14513be24 Parshuram Thombare 2020-11-29 1816 */
5386a14513be24 Parshuram Thombare 2020-11-29 1817 static int i3c_secondary_master_bus_init(struct i3c_master_controller *master)
5386a14513be24 Parshuram Thombare 2020-11-29 1818 {
5386a14513be24 Parshuram Thombare 2020-11-29 1819 enum i3c_addr_slot_status status;
5386a14513be24 Parshuram Thombare 2020-11-29 1820 struct i2c_dev_boardinfo *i2cboardinfo;
5386a14513be24 Parshuram Thombare 2020-11-29 1821 struct i2c_dev_desc *i2cdev;
5386a14513be24 Parshuram Thombare 2020-11-29 1822 int ret;
5386a14513be24 Parshuram Thombare 2020-11-29 1823
5386a14513be24 Parshuram Thombare 2020-11-29 1824 /*
5386a14513be24 Parshuram Thombare 2020-11-29 1825 * First attach all devices with static definitions provided by the
5386a14513be24 Parshuram Thombare 2020-11-29 1826 * FW.
5386a14513be24 Parshuram Thombare 2020-11-29 1827 */
5386a14513be24 Parshuram Thombare 2020-11-29 1828 list_for_each_entry(i2cboardinfo, &master->boardinfo.i2c, node) {
5386a14513be24 Parshuram Thombare 2020-11-29 1829 status = i3c_bus_get_addr_slot_status(&master->bus,
5386a14513be24 Parshuram Thombare 2020-11-29 1830 i2cboardinfo->base.addr);
5386a14513be24 Parshuram Thombare 2020-11-29 1831 if (status != I3C_ADDR_SLOT_FREE) {
5386a14513be24 Parshuram Thombare 2020-11-29 1832 ret = -EBUSY;
5386a14513be24 Parshuram Thombare 2020-11-29 1833 goto err_detach_devs;
5386a14513be24 Parshuram Thombare 2020-11-29 1834 }
5386a14513be24 Parshuram Thombare 2020-11-29 1835
5386a14513be24 Parshuram Thombare 2020-11-29 1836 i3c_bus_set_addr_slot_status(&master->bus,
5386a14513be24 Parshuram Thombare 2020-11-29 1837 i2cboardinfo->base.addr,
5386a14513be24 Parshuram Thombare 2020-11-29 1838 I3C_ADDR_SLOT_I2C_DEV);
5386a14513be24 Parshuram Thombare 2020-11-29 1839
5386a14513be24 Parshuram Thombare 2020-11-29 1840 i2cdev = i3c_master_alloc_i2c_dev(master, i2cboardinfo);
5386a14513be24 Parshuram Thombare 2020-11-29 1841 if (IS_ERR(i2cdev)) {
5386a14513be24 Parshuram Thombare 2020-11-29 @1842 ret = PTR_ERR(i2cdev);
5386a14513be24 Parshuram Thombare 2020-11-29 1843 goto err_detach_devs;
5386a14513be24 Parshuram Thombare 2020-11-29 1844 }
5386a14513be24 Parshuram Thombare 2020-11-29 1845
5386a14513be24 Parshuram Thombare 2020-11-29 1846 ret = i3c_master_attach_i2c_dev(master, i2cdev);
5386a14513be24 Parshuram Thombare 2020-11-29 1847 if (ret) {
5386a14513be24 Parshuram Thombare 2020-11-29 1848 i3c_master_free_i2c_dev(i2cdev);
5386a14513be24 Parshuram Thombare 2020-11-29 1849 goto err_detach_devs;
5386a14513be24 Parshuram Thombare 2020-11-29 1850 }
5386a14513be24 Parshuram Thombare 2020-11-29 1851 }
5386a14513be24 Parshuram Thombare 2020-11-29 1852
5386a14513be24 Parshuram Thombare 2020-11-29 1853 /*
5386a14513be24 Parshuram Thombare 2020-11-29 1854 * Now execute the controller specific ->bus_init() routine, which
5386a14513be24 Parshuram Thombare 2020-11-29 1855 * might configure its internal logic to match the bus limitations.
5386a14513be24 Parshuram Thombare 2020-11-29 1856 */
5386a14513be24 Parshuram Thombare 2020-11-29 1857 ret = master->ops->bus_init(master);
5386a14513be24 Parshuram Thombare 2020-11-29 1858 if (ret)
5386a14513be24 Parshuram Thombare 2020-11-29 1859 goto err_detach_devs;
5386a14513be24 Parshuram Thombare 2020-11-29 1860
5386a14513be24 Parshuram Thombare 2020-11-29 1861 /*
5386a14513be24 Parshuram Thombare 2020-11-29 1862 * The master device should have been instantiated in ->bus_init(),
5386a14513be24 Parshuram Thombare 2020-11-29 1863 * complain if this was not the case.
5386a14513be24 Parshuram Thombare 2020-11-29 1864 */
5386a14513be24 Parshuram Thombare 2020-11-29 1865 if (!master->this) {
5386a14513be24 Parshuram Thombare 2020-11-29 1866 dev_err(&master->dev,
5386a14513be24 Parshuram Thombare 2020-11-29 1867 "master_set_info() was not called in ->bus_init()\n");
5386a14513be24 Parshuram Thombare 2020-11-29 1868 ret = -EINVAL;
5386a14513be24 Parshuram Thombare 2020-11-29 1869 goto err_bus_cleanup;
5386a14513be24 Parshuram Thombare 2020-11-29 1870 }
5386a14513be24 Parshuram Thombare 2020-11-29 1871
5386a14513be24 Parshuram Thombare 2020-11-29 1872 return 0;
5386a14513be24 Parshuram Thombare 2020-11-29 1873
5386a14513be24 Parshuram Thombare 2020-11-29 1874 err_bus_cleanup:
5386a14513be24 Parshuram Thombare 2020-11-29 1875 if (master->ops->bus_cleanup)
5386a14513be24 Parshuram Thombare 2020-11-29 1876 master->ops->bus_cleanup(master);
5386a14513be24 Parshuram Thombare 2020-11-29 1877
5386a14513be24 Parshuram Thombare 2020-11-29 1878 err_detach_devs:
5386a14513be24 Parshuram Thombare 2020-11-29 1879 i3c_master_detach_free_devs(master);
5386a14513be24 Parshuram Thombare 2020-11-29 1880
5386a14513be24 Parshuram Thombare 2020-11-29 1881 return ret;
5386a14513be24 Parshuram Thombare 2020-11-29 1882 }
5386a14513be24 Parshuram Thombare 2020-11-29 1883
---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all(a)lists.01.org
[-- Attachment #2: config.gz --]
[-- Type: application/gzip, Size: 34628 bytes --]
^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH v9 3/7] i3c: master: add i3c_secondary_master_register
2020-11-29 14:19 [RESEND PATCH v9 0/7] I3C mastership handover support Parshuram Thombare
@ 2020-11-29 14:22 ` Parshuram Thombare
0 siblings, 0 replies; 5+ messages in thread
From: Parshuram Thombare @ 2020-11-29 14:22 UTC (permalink / raw)
To: alexandre.belloni, slongerbeam, vitor.soares
Cc: linux-i3c, linux-kernel, mparab, praneeth, Parshuram Thombare
add i3c_secondary_master_register which is used
to register secondary masters.
Signed-off-by: Parshuram Thombare <pthombar@cadence.com>
---
drivers/i3c/master.c | 154 +++++++++++++++++++++++++++++++++++++++++++-
include/linux/i3c/master.h | 3 +
2 files changed, 156 insertions(+), 1 deletions(-)
diff --git a/drivers/i3c/master.c b/drivers/i3c/master.c
index 56e8fe4..af0630a 100644
--- a/drivers/i3c/master.c
+++ b/drivers/i3c/master.c
@@ -1797,6 +1797,90 @@ static int i3c_primary_master_bus_init(struct i3c_master_controller *master)
return ret;
}
+/**
+ * i3c_secondary_master_bus_init() - initialize an I3C bus for secondary
+ * master
+ * @master: secondary master initializing the bus
+ *
+ * This function does
+ *
+ * 1. Attach I2C devs to the master
+ *
+ * 2. Call &i3c_master_controller_ops->bus_init() method to initialize
+ * the master controller. That's usually where the bus mode is selected
+ * (pure bus or mixed fast/slow bus)
+ *
+ * Once this is done, I2C devices should be usable.
+ *
+ * Return: a 0 in case of success, an negative error code otherwise.
+ */
+static int i3c_secondary_master_bus_init(struct i3c_master_controller *master)
+{
+ enum i3c_addr_slot_status status;
+ struct i2c_dev_boardinfo *i2cboardinfo;
+ struct i2c_dev_desc *i2cdev;
+ int ret;
+
+ /*
+ * First attach all devices with static definitions provided by the
+ * FW.
+ */
+ list_for_each_entry(i2cboardinfo, &master->boardinfo.i2c, node) {
+ status = i3c_bus_get_addr_slot_status(&master->bus,
+ i2cboardinfo->base.addr);
+ if (status != I3C_ADDR_SLOT_FREE) {
+ ret = -EBUSY;
+ goto err_detach_devs;
+ }
+
+ i3c_bus_set_addr_slot_status(&master->bus,
+ i2cboardinfo->base.addr,
+ I3C_ADDR_SLOT_I2C_DEV);
+
+ i2cdev = i3c_master_alloc_i2c_dev(master, i2cboardinfo);
+ if (IS_ERR(i2cdev)) {
+ ret = PTR_ERR(i2cdev);
+ goto err_detach_devs;
+ }
+
+ ret = i3c_master_attach_i2c_dev(master, i2cdev);
+ if (ret) {
+ i3c_master_free_i2c_dev(i2cdev);
+ goto err_detach_devs;
+ }
+ }
+
+ /*
+ * Now execute the controller specific ->bus_init() routine, which
+ * might configure its internal logic to match the bus limitations.
+ */
+ ret = master->ops->bus_init(master);
+ if (ret)
+ goto err_detach_devs;
+
+ /*
+ * The master device should have been instantiated in ->bus_init(),
+ * complain if this was not the case.
+ */
+ if (!master->this) {
+ dev_err(&master->dev,
+ "master_set_info() was not called in ->bus_init()\n");
+ ret = -EINVAL;
+ goto err_bus_cleanup;
+ }
+
+ return 0;
+
+err_bus_cleanup:
+ if (master->ops->bus_cleanup)
+ master->ops->bus_cleanup(master);
+
+err_detach_devs:
+ i3c_master_detach_free_devs(master);
+
+ return ret;
+}
+
static void i3c_master_bus_cleanup(struct i3c_master_controller *master)
{
if (master->ops->bus_cleanup)
@@ -2514,7 +2598,10 @@ static int i3c_master_init(struct i3c_master_controller *master,
goto err_put_dev;
}
- ret = i3c_primary_master_bus_init(master);
+ if (secondary)
+ ret = i3c_secondary_master_bus_init(master);
+ else
+ ret = i3c_primary_master_bus_init(master);
if (ret)
goto err_destroy_wq;
@@ -2595,6 +2682,71 @@ int i3c_primary_master_register(struct i3c_master_controller *master,
EXPORT_SYMBOL_GPL(i3c_primary_master_register);
/**
+ * i3c_secondary_master_register() - register an I3C secondary master
+ * @master: master used to send frames on the bus
+ * @parent: the parent device (the one that provides this I3C master
+ * controller)
+ * @ops: the master controller operations
+ *
+ * This function does minimal required initialization for secondary
+ * master, rest functionality like creating and registering I2C
+ * and I3C devices is done in defslvs processing.
+ *
+ * i3c_secondary_master_register() does following things -
+ * - creates and initializes the I3C bus
+ * - populates the bus with static I2C devs if @parent->of_node is not
+ * NULL
+ * initialization
+ * - allocate memory for defslvs_data.devs, which is used to receive
+ * defslvs list
+ * - create I3C device representing this master
+ * - registers the I2C adapter and all I2C devices
+ *
+ * Return: 0 in case of success, a negative error code otherwise.
+ */
+int i3c_secondary_master_register(struct i3c_master_controller *master,
+ struct device *parent,
+ const struct i3c_master_controller_ops *ops)
+{
+ int ret;
+
+ ret = i3c_master_init(master, parent, ops, true);
+ if (ret)
+ return ret;
+
+ ret = device_add(&master->dev);
+ if (ret)
+ goto err_cleanup_bus;
+
+ /*
+ * Expose our I3C bus as an I2C adapter so that I2C devices are exposed
+ * through the I2C subsystem.
+ */
+ ret = i3c_master_i2c_adapter_init(master);
+ if (ret)
+ goto err_del_dev;
+
+ /*
+ * We're done initializing the bus and the controller, we can now
+ * register I3C devices from defslvs list.
+ */
+ master->init_done = true;
+
+ return 0;
+
+err_del_dev:
+ device_del(&master->dev);
+
+err_cleanup_bus:
+ i3c_master_bus_cleanup(master);
+
+ put_device(&master->dev);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(i3c_secondary_master_register);
+
+/**
* i3c_master_unregister() - unregister an I3C master
* @master: master used to send frames on the bus
*
diff --git a/include/linux/i3c/master.h b/include/linux/i3c/master.h
index e543f68..e186d53 100644
--- a/include/linux/i3c/master.h
+++ b/include/linux/i3c/master.h
@@ -541,6 +541,9 @@ int i3c_master_set_info(struct i3c_master_controller *master,
int i3c_primary_master_register(struct i3c_master_controller *master,
struct device *parent,
const struct i3c_master_controller_ops *ops);
+int i3c_secondary_master_register(struct i3c_master_controller *master,
+ struct device *parent,
+ const struct i3c_master_controller_ops *ops);
int i3c_master_unregister(struct i3c_master_controller *master);
/**
--
1.7.1
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH v9 3/7] i3c: master: add i3c_secondary_master_register
@ 2020-11-29 14:22 ` Parshuram Thombare
0 siblings, 0 replies; 5+ messages in thread
From: Parshuram Thombare @ 2020-11-29 14:22 UTC (permalink / raw)
To: alexandre.belloni, slongerbeam, vitor.soares
Cc: praneeth, mparab, linux-i3c, linux-kernel, Parshuram Thombare
add i3c_secondary_master_register which is used
to register secondary masters.
Signed-off-by: Parshuram Thombare <pthombar@cadence.com>
---
drivers/i3c/master.c | 154 +++++++++++++++++++++++++++++++++++++++++++-
include/linux/i3c/master.h | 3 +
2 files changed, 156 insertions(+), 1 deletions(-)
diff --git a/drivers/i3c/master.c b/drivers/i3c/master.c
index 56e8fe4..af0630a 100644
--- a/drivers/i3c/master.c
+++ b/drivers/i3c/master.c
@@ -1797,6 +1797,90 @@ static int i3c_primary_master_bus_init(struct i3c_master_controller *master)
return ret;
}
+/**
+ * i3c_secondary_master_bus_init() - initialize an I3C bus for secondary
+ * master
+ * @master: secondary master initializing the bus
+ *
+ * This function does
+ *
+ * 1. Attach I2C devs to the master
+ *
+ * 2. Call &i3c_master_controller_ops->bus_init() method to initialize
+ * the master controller. That's usually where the bus mode is selected
+ * (pure bus or mixed fast/slow bus)
+ *
+ * Once this is done, I2C devices should be usable.
+ *
+ * Return: a 0 in case of success, an negative error code otherwise.
+ */
+static int i3c_secondary_master_bus_init(struct i3c_master_controller *master)
+{
+ enum i3c_addr_slot_status status;
+ struct i2c_dev_boardinfo *i2cboardinfo;
+ struct i2c_dev_desc *i2cdev;
+ int ret;
+
+ /*
+ * First attach all devices with static definitions provided by the
+ * FW.
+ */
+ list_for_each_entry(i2cboardinfo, &master->boardinfo.i2c, node) {
+ status = i3c_bus_get_addr_slot_status(&master->bus,
+ i2cboardinfo->base.addr);
+ if (status != I3C_ADDR_SLOT_FREE) {
+ ret = -EBUSY;
+ goto err_detach_devs;
+ }
+
+ i3c_bus_set_addr_slot_status(&master->bus,
+ i2cboardinfo->base.addr,
+ I3C_ADDR_SLOT_I2C_DEV);
+
+ i2cdev = i3c_master_alloc_i2c_dev(master, i2cboardinfo);
+ if (IS_ERR(i2cdev)) {
+ ret = PTR_ERR(i2cdev);
+ goto err_detach_devs;
+ }
+
+ ret = i3c_master_attach_i2c_dev(master, i2cdev);
+ if (ret) {
+ i3c_master_free_i2c_dev(i2cdev);
+ goto err_detach_devs;
+ }
+ }
+
+ /*
+ * Now execute the controller specific ->bus_init() routine, which
+ * might configure its internal logic to match the bus limitations.
+ */
+ ret = master->ops->bus_init(master);
+ if (ret)
+ goto err_detach_devs;
+
+ /*
+ * The master device should have been instantiated in ->bus_init(),
+ * complain if this was not the case.
+ */
+ if (!master->this) {
+ dev_err(&master->dev,
+ "master_set_info() was not called in ->bus_init()\n");
+ ret = -EINVAL;
+ goto err_bus_cleanup;
+ }
+
+ return 0;
+
+err_bus_cleanup:
+ if (master->ops->bus_cleanup)
+ master->ops->bus_cleanup(master);
+
+err_detach_devs:
+ i3c_master_detach_free_devs(master);
+
+ return ret;
+}
+
static void i3c_master_bus_cleanup(struct i3c_master_controller *master)
{
if (master->ops->bus_cleanup)
@@ -2514,7 +2598,10 @@ static int i3c_master_init(struct i3c_master_controller *master,
goto err_put_dev;
}
- ret = i3c_primary_master_bus_init(master);
+ if (secondary)
+ ret = i3c_secondary_master_bus_init(master);
+ else
+ ret = i3c_primary_master_bus_init(master);
if (ret)
goto err_destroy_wq;
@@ -2595,6 +2682,71 @@ int i3c_primary_master_register(struct i3c_master_controller *master,
EXPORT_SYMBOL_GPL(i3c_primary_master_register);
/**
+ * i3c_secondary_master_register() - register an I3C secondary master
+ * @master: master used to send frames on the bus
+ * @parent: the parent device (the one that provides this I3C master
+ * controller)
+ * @ops: the master controller operations
+ *
+ * This function does minimal required initialization for secondary
+ * master, rest functionality like creating and registering I2C
+ * and I3C devices is done in defslvs processing.
+ *
+ * i3c_secondary_master_register() does following things -
+ * - creates and initializes the I3C bus
+ * - populates the bus with static I2C devs if @parent->of_node is not
+ * NULL
+ * initialization
+ * - allocate memory for defslvs_data.devs, which is used to receive
+ * defslvs list
+ * - create I3C device representing this master
+ * - registers the I2C adapter and all I2C devices
+ *
+ * Return: 0 in case of success, a negative error code otherwise.
+ */
+int i3c_secondary_master_register(struct i3c_master_controller *master,
+ struct device *parent,
+ const struct i3c_master_controller_ops *ops)
+{
+ int ret;
+
+ ret = i3c_master_init(master, parent, ops, true);
+ if (ret)
+ return ret;
+
+ ret = device_add(&master->dev);
+ if (ret)
+ goto err_cleanup_bus;
+
+ /*
+ * Expose our I3C bus as an I2C adapter so that I2C devices are exposed
+ * through the I2C subsystem.
+ */
+ ret = i3c_master_i2c_adapter_init(master);
+ if (ret)
+ goto err_del_dev;
+
+ /*
+ * We're done initializing the bus and the controller, we can now
+ * register I3C devices from defslvs list.
+ */
+ master->init_done = true;
+
+ return 0;
+
+err_del_dev:
+ device_del(&master->dev);
+
+err_cleanup_bus:
+ i3c_master_bus_cleanup(master);
+
+ put_device(&master->dev);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(i3c_secondary_master_register);
+
+/**
* i3c_master_unregister() - unregister an I3C master
* @master: master used to send frames on the bus
*
diff --git a/include/linux/i3c/master.h b/include/linux/i3c/master.h
index e543f68..e186d53 100644
--- a/include/linux/i3c/master.h
+++ b/include/linux/i3c/master.h
@@ -541,6 +541,9 @@ int i3c_master_set_info(struct i3c_master_controller *master,
int i3c_primary_master_register(struct i3c_master_controller *master,
struct device *parent,
const struct i3c_master_controller_ops *ops);
+int i3c_secondary_master_register(struct i3c_master_controller *master,
+ struct device *parent,
+ const struct i3c_master_controller_ops *ops);
int i3c_master_unregister(struct i3c_master_controller *master);
/**
--
1.7.1
--
linux-i3c mailing list
linux-i3c@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-i3c
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH v9 3/7] i3c: master: add i3c_secondary_master_register
@ 2020-11-28 14:46 ` Parshuram Thombare
0 siblings, 0 replies; 5+ messages in thread
From: Parshuram Thombare @ 2020-11-28 14:46 UTC (permalink / raw)
To: alexandre.belloni, slongerbeam, vitor.soares
Cc: linux-i3c, linux-kernel, mparab, praneeth, Parshuram Thombare
add i3c_secondary_master_register which is used
to register secondary masters.
Signed-off-by: Parshuram Thombare <pthombar@cadence.com>
---
drivers/i3c/master.c | 154 +++++++++++++++++++++++++++++++++++++++++++-
include/linux/i3c/master.h | 3 +
2 files changed, 156 insertions(+), 1 deletions(-)
diff --git a/drivers/i3c/master.c b/drivers/i3c/master.c
index 56e8fe4..af0630a 100644
--- a/drivers/i3c/master.c
+++ b/drivers/i3c/master.c
@@ -1797,6 +1797,90 @@ static int i3c_primary_master_bus_init(struct i3c_master_controller *master)
return ret;
}
+/**
+ * i3c_secondary_master_bus_init() - initialize an I3C bus for secondary
+ * master
+ * @master: secondary master initializing the bus
+ *
+ * This function does
+ *
+ * 1. Attach I2C devs to the master
+ *
+ * 2. Call &i3c_master_controller_ops->bus_init() method to initialize
+ * the master controller. That's usually where the bus mode is selected
+ * (pure bus or mixed fast/slow bus)
+ *
+ * Once this is done, I2C devices should be usable.
+ *
+ * Return: a 0 in case of success, an negative error code otherwise.
+ */
+static int i3c_secondary_master_bus_init(struct i3c_master_controller *master)
+{
+ enum i3c_addr_slot_status status;
+ struct i2c_dev_boardinfo *i2cboardinfo;
+ struct i2c_dev_desc *i2cdev;
+ int ret;
+
+ /*
+ * First attach all devices with static definitions provided by the
+ * FW.
+ */
+ list_for_each_entry(i2cboardinfo, &master->boardinfo.i2c, node) {
+ status = i3c_bus_get_addr_slot_status(&master->bus,
+ i2cboardinfo->base.addr);
+ if (status != I3C_ADDR_SLOT_FREE) {
+ ret = -EBUSY;
+ goto err_detach_devs;
+ }
+
+ i3c_bus_set_addr_slot_status(&master->bus,
+ i2cboardinfo->base.addr,
+ I3C_ADDR_SLOT_I2C_DEV);
+
+ i2cdev = i3c_master_alloc_i2c_dev(master, i2cboardinfo);
+ if (IS_ERR(i2cdev)) {
+ ret = PTR_ERR(i2cdev);
+ goto err_detach_devs;
+ }
+
+ ret = i3c_master_attach_i2c_dev(master, i2cdev);
+ if (ret) {
+ i3c_master_free_i2c_dev(i2cdev);
+ goto err_detach_devs;
+ }
+ }
+
+ /*
+ * Now execute the controller specific ->bus_init() routine, which
+ * might configure its internal logic to match the bus limitations.
+ */
+ ret = master->ops->bus_init(master);
+ if (ret)
+ goto err_detach_devs;
+
+ /*
+ * The master device should have been instantiated in ->bus_init(),
+ * complain if this was not the case.
+ */
+ if (!master->this) {
+ dev_err(&master->dev,
+ "master_set_info() was not called in ->bus_init()\n");
+ ret = -EINVAL;
+ goto err_bus_cleanup;
+ }
+
+ return 0;
+
+err_bus_cleanup:
+ if (master->ops->bus_cleanup)
+ master->ops->bus_cleanup(master);
+
+err_detach_devs:
+ i3c_master_detach_free_devs(master);
+
+ return ret;
+}
+
static void i3c_master_bus_cleanup(struct i3c_master_controller *master)
{
if (master->ops->bus_cleanup)
@@ -2514,7 +2598,10 @@ static int i3c_master_init(struct i3c_master_controller *master,
goto err_put_dev;
}
- ret = i3c_primary_master_bus_init(master);
+ if (secondary)
+ ret = i3c_secondary_master_bus_init(master);
+ else
+ ret = i3c_primary_master_bus_init(master);
if (ret)
goto err_destroy_wq;
@@ -2595,6 +2682,71 @@ int i3c_primary_master_register(struct i3c_master_controller *master,
EXPORT_SYMBOL_GPL(i3c_primary_master_register);
/**
+ * i3c_secondary_master_register() - register an I3C secondary master
+ * @master: master used to send frames on the bus
+ * @parent: the parent device (the one that provides this I3C master
+ * controller)
+ * @ops: the master controller operations
+ *
+ * This function does minimal required initialization for secondary
+ * master, rest functionality like creating and registering I2C
+ * and I3C devices is done in defslvs processing.
+ *
+ * i3c_secondary_master_register() does following things -
+ * - creates and initializes the I3C bus
+ * - populates the bus with static I2C devs if @parent->of_node is not
+ * NULL
+ * initialization
+ * - allocate memory for defslvs_data.devs, which is used to receive
+ * defslvs list
+ * - create I3C device representing this master
+ * - registers the I2C adapter and all I2C devices
+ *
+ * Return: 0 in case of success, a negative error code otherwise.
+ */
+int i3c_secondary_master_register(struct i3c_master_controller *master,
+ struct device *parent,
+ const struct i3c_master_controller_ops *ops)
+{
+ int ret;
+
+ ret = i3c_master_init(master, parent, ops, true);
+ if (ret)
+ return ret;
+
+ ret = device_add(&master->dev);
+ if (ret)
+ goto err_cleanup_bus;
+
+ /*
+ * Expose our I3C bus as an I2C adapter so that I2C devices are exposed
+ * through the I2C subsystem.
+ */
+ ret = i3c_master_i2c_adapter_init(master);
+ if (ret)
+ goto err_del_dev;
+
+ /*
+ * We're done initializing the bus and the controller, we can now
+ * register I3C devices from defslvs list.
+ */
+ master->init_done = true;
+
+ return 0;
+
+err_del_dev:
+ device_del(&master->dev);
+
+err_cleanup_bus:
+ i3c_master_bus_cleanup(master);
+
+ put_device(&master->dev);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(i3c_secondary_master_register);
+
+/**
* i3c_master_unregister() - unregister an I3C master
* @master: master used to send frames on the bus
*
diff --git a/include/linux/i3c/master.h b/include/linux/i3c/master.h
index e543f68..e186d53 100644
--- a/include/linux/i3c/master.h
+++ b/include/linux/i3c/master.h
@@ -541,6 +541,9 @@ int i3c_master_set_info(struct i3c_master_controller *master,
int i3c_primary_master_register(struct i3c_master_controller *master,
struct device *parent,
const struct i3c_master_controller_ops *ops);
+int i3c_secondary_master_register(struct i3c_master_controller *master,
+ struct device *parent,
+ const struct i3c_master_controller_ops *ops);
int i3c_master_unregister(struct i3c_master_controller *master);
/**
--
1.7.1
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH v9 3/7] i3c: master: add i3c_secondary_master_register
@ 2020-11-28 14:46 ` Parshuram Thombare
0 siblings, 0 replies; 5+ messages in thread
From: Parshuram Thombare @ 2020-11-28 14:46 UTC (permalink / raw)
To: alexandre.belloni, slongerbeam, vitor.soares
Cc: praneeth, mparab, linux-i3c, linux-kernel, Parshuram Thombare
add i3c_secondary_master_register which is used
to register secondary masters.
Signed-off-by: Parshuram Thombare <pthombar@cadence.com>
---
drivers/i3c/master.c | 154 +++++++++++++++++++++++++++++++++++++++++++-
include/linux/i3c/master.h | 3 +
2 files changed, 156 insertions(+), 1 deletions(-)
diff --git a/drivers/i3c/master.c b/drivers/i3c/master.c
index 56e8fe4..af0630a 100644
--- a/drivers/i3c/master.c
+++ b/drivers/i3c/master.c
@@ -1797,6 +1797,90 @@ static int i3c_primary_master_bus_init(struct i3c_master_controller *master)
return ret;
}
+/**
+ * i3c_secondary_master_bus_init() - initialize an I3C bus for secondary
+ * master
+ * @master: secondary master initializing the bus
+ *
+ * This function does
+ *
+ * 1. Attach I2C devs to the master
+ *
+ * 2. Call &i3c_master_controller_ops->bus_init() method to initialize
+ * the master controller. That's usually where the bus mode is selected
+ * (pure bus or mixed fast/slow bus)
+ *
+ * Once this is done, I2C devices should be usable.
+ *
+ * Return: a 0 in case of success, an negative error code otherwise.
+ */
+static int i3c_secondary_master_bus_init(struct i3c_master_controller *master)
+{
+ enum i3c_addr_slot_status status;
+ struct i2c_dev_boardinfo *i2cboardinfo;
+ struct i2c_dev_desc *i2cdev;
+ int ret;
+
+ /*
+ * First attach all devices with static definitions provided by the
+ * FW.
+ */
+ list_for_each_entry(i2cboardinfo, &master->boardinfo.i2c, node) {
+ status = i3c_bus_get_addr_slot_status(&master->bus,
+ i2cboardinfo->base.addr);
+ if (status != I3C_ADDR_SLOT_FREE) {
+ ret = -EBUSY;
+ goto err_detach_devs;
+ }
+
+ i3c_bus_set_addr_slot_status(&master->bus,
+ i2cboardinfo->base.addr,
+ I3C_ADDR_SLOT_I2C_DEV);
+
+ i2cdev = i3c_master_alloc_i2c_dev(master, i2cboardinfo);
+ if (IS_ERR(i2cdev)) {
+ ret = PTR_ERR(i2cdev);
+ goto err_detach_devs;
+ }
+
+ ret = i3c_master_attach_i2c_dev(master, i2cdev);
+ if (ret) {
+ i3c_master_free_i2c_dev(i2cdev);
+ goto err_detach_devs;
+ }
+ }
+
+ /*
+ * Now execute the controller specific ->bus_init() routine, which
+ * might configure its internal logic to match the bus limitations.
+ */
+ ret = master->ops->bus_init(master);
+ if (ret)
+ goto err_detach_devs;
+
+ /*
+ * The master device should have been instantiated in ->bus_init(),
+ * complain if this was not the case.
+ */
+ if (!master->this) {
+ dev_err(&master->dev,
+ "master_set_info() was not called in ->bus_init()\n");
+ ret = -EINVAL;
+ goto err_bus_cleanup;
+ }
+
+ return 0;
+
+err_bus_cleanup:
+ if (master->ops->bus_cleanup)
+ master->ops->bus_cleanup(master);
+
+err_detach_devs:
+ i3c_master_detach_free_devs(master);
+
+ return ret;
+}
+
static void i3c_master_bus_cleanup(struct i3c_master_controller *master)
{
if (master->ops->bus_cleanup)
@@ -2514,7 +2598,10 @@ static int i3c_master_init(struct i3c_master_controller *master,
goto err_put_dev;
}
- ret = i3c_primary_master_bus_init(master);
+ if (secondary)
+ ret = i3c_secondary_master_bus_init(master);
+ else
+ ret = i3c_primary_master_bus_init(master);
if (ret)
goto err_destroy_wq;
@@ -2595,6 +2682,71 @@ int i3c_primary_master_register(struct i3c_master_controller *master,
EXPORT_SYMBOL_GPL(i3c_primary_master_register);
/**
+ * i3c_secondary_master_register() - register an I3C secondary master
+ * @master: master used to send frames on the bus
+ * @parent: the parent device (the one that provides this I3C master
+ * controller)
+ * @ops: the master controller operations
+ *
+ * This function does minimal required initialization for secondary
+ * master, rest functionality like creating and registering I2C
+ * and I3C devices is done in defslvs processing.
+ *
+ * i3c_secondary_master_register() does following things -
+ * - creates and initializes the I3C bus
+ * - populates the bus with static I2C devs if @parent->of_node is not
+ * NULL
+ * initialization
+ * - allocate memory for defslvs_data.devs, which is used to receive
+ * defslvs list
+ * - create I3C device representing this master
+ * - registers the I2C adapter and all I2C devices
+ *
+ * Return: 0 in case of success, a negative error code otherwise.
+ */
+int i3c_secondary_master_register(struct i3c_master_controller *master,
+ struct device *parent,
+ const struct i3c_master_controller_ops *ops)
+{
+ int ret;
+
+ ret = i3c_master_init(master, parent, ops, true);
+ if (ret)
+ return ret;
+
+ ret = device_add(&master->dev);
+ if (ret)
+ goto err_cleanup_bus;
+
+ /*
+ * Expose our I3C bus as an I2C adapter so that I2C devices are exposed
+ * through the I2C subsystem.
+ */
+ ret = i3c_master_i2c_adapter_init(master);
+ if (ret)
+ goto err_del_dev;
+
+ /*
+ * We're done initializing the bus and the controller, we can now
+ * register I3C devices from defslvs list.
+ */
+ master->init_done = true;
+
+ return 0;
+
+err_del_dev:
+ device_del(&master->dev);
+
+err_cleanup_bus:
+ i3c_master_bus_cleanup(master);
+
+ put_device(&master->dev);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(i3c_secondary_master_register);
+
+/**
* i3c_master_unregister() - unregister an I3C master
* @master: master used to send frames on the bus
*
diff --git a/include/linux/i3c/master.h b/include/linux/i3c/master.h
index e543f68..e186d53 100644
--- a/include/linux/i3c/master.h
+++ b/include/linux/i3c/master.h
@@ -541,6 +541,9 @@ int i3c_master_set_info(struct i3c_master_controller *master,
int i3c_primary_master_register(struct i3c_master_controller *master,
struct device *parent,
const struct i3c_master_controller_ops *ops);
+int i3c_secondary_master_register(struct i3c_master_controller *master,
+ struct device *parent,
+ const struct i3c_master_controller_ops *ops);
int i3c_master_unregister(struct i3c_master_controller *master);
/**
--
1.7.1
--
linux-i3c mailing list
linux-i3c@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-i3c
^ permalink raw reply related [flat|nested] 5+ messages in thread
end of thread, other threads:[~2020-11-29 17:38 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-11-29 17:38 [PATCH v9 3/7] i3c: master: add i3c_secondary_master_register kernel test robot
-- strict thread matches above, loose matches on Subject: below --
2020-11-29 14:19 [RESEND PATCH v9 0/7] I3C mastership handover support Parshuram Thombare
2020-11-29 14:22 ` [PATCH v9 3/7] i3c: master: add i3c_secondary_master_register Parshuram Thombare
2020-11-29 14:22 ` Parshuram Thombare
2020-11-28 14:46 Parshuram Thombare
2020-11-28 14:46 ` Parshuram Thombare
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.