Add support for I3C device in the tmp108 driver to handle the P3T1085
sensor. Register the I3C device driver to enable I3C functionality for the
sensor.
Signed-off-by: Frank Li <Frank.Li@nxp.com>
---
change from v2 to v3
- change kconfig to select REGMAP_I3C if enable i3c
- remove i3c/master.h
- remove , after {}
- use #ifdef CONFIG_I3C about i3c register code
I2C I3C
Y Y support both
Y N i3c part code will not be compiled
N Y whole TPM108 will not be compiled
N N whole TPM108 will not be compiled
---
drivers/hwmon/Kconfig | 1 +
drivers/hwmon/tmp108.c | 31 +++++++++++++++++++++++++++++++
2 files changed, 32 insertions(+)
diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
index d43ca7aa4a548..9579db7849e1f 100644
--- a/drivers/hwmon/Kconfig
+++ b/drivers/hwmon/Kconfig
@@ -2298,6 +2298,7 @@ config SENSORS_TMP108
tristate "Texas Instruments TMP108"
depends on I2C
select REGMAP_I2C
+ select REGMAP_I3C if I3C
help
If you say yes here you get support for Texas Instruments TMP108
sensor chips and NXP P3T1085.
diff --git a/drivers/hwmon/tmp108.c b/drivers/hwmon/tmp108.c
index bfbea6349a95f..deb1505321335 100644
--- a/drivers/hwmon/tmp108.c
+++ b/drivers/hwmon/tmp108.c
@@ -13,6 +13,7 @@
#include <linux/mutex.h>
#include <linux/of.h>
#include <linux/i2c.h>
+#include <linux/i3c/device.h>
#include <linux/init.h>
#include <linux/jiffies.h>
#include <linux/regmap.h>
@@ -442,6 +443,36 @@ static struct i2c_driver tmp108_driver = {
module_i2c_driver(tmp108_driver);
+#ifdef CONFIG_I3C
+static const struct i3c_device_id p3t1085_i3c_ids[] = {
+ I3C_DEVICE(0x011b, 0x1529, NULL),
+ {}
+};
+MODULE_DEVICE_TABLE(i3c, p3t1085_i3c_ids);
+
+static int p3t1085_i3c_probe(struct i3c_device *i3cdev)
+{
+ struct device *dev = i3cdev_to_dev(i3cdev);
+ struct regmap *regmap;
+
+ regmap = devm_regmap_init_i3c(i3cdev, &tmp108_regmap_config);
+ if (IS_ERR(regmap))
+ return dev_err_probe(dev, PTR_ERR(regmap),
+ "Failed to register i3c regmap\n");
+
+ return tmp108_common_probe(dev, regmap, "p3t1085_i3c");
+}
+
+static struct i3c_driver p3t1085_driver = {
+ .driver = {
+ .name = "p3t1085_i3c",
+ },
+ .probe = p3t1085_i3c_probe,
+ .id_table = p3t1085_i3c_ids,
+};
+module_i3c_driver(p3t1085_driver);
+#endif
+
MODULE_AUTHOR("John Muir <john@jmuir.com>");
MODULE_DESCRIPTION("Texas Instruments TMP108 temperature sensor driver");
MODULE_LICENSE("GPL");
--
2.34.1
Hi Frank,
kernel test robot noticed the following build errors:
[auto build test ERROR on 74741a050b79d31d8d2eeee12c77736596d0a6b2]
url: https://github.com/intel-lab-lkp/linux/commits/Frank-Li/dt-bindings-hwmon-ti-tmp108-Add-nxp-p3t1085-compatible-string/20241112-013721
base: 74741a050b79d31d8d2eeee12c77736596d0a6b2
patch link: https://lore.kernel.org/r/20241111-p3t1085-v3-4-bff511550aad%40nxp.com
patch subject: [PATCH v3 4/5] hwmon: tmp108: Add support for I3C device
config: arc-randconfig-001-20241114 (https://download.01.org/0day-ci/archive/20241114/202411141530.qTxjCzf7-lkp@intel.com/config)
compiler: arceb-elf-gcc (GCC) 13.2.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20241114/202411141530.qTxjCzf7-lkp@intel.com/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 <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202411141530.qTxjCzf7-lkp@intel.com/
All errors (new ones prefixed by >>):
In file included from include/linux/device/driver.h:21,
from include/linux/device.h:32,
from drivers/hwmon/tmp108.c:8:
>> include/linux/module.h:131:49: error: redefinition of '__inittest'
131 | static inline initcall_t __maybe_unused __inittest(void) \
| ^~~~~~~~~~
include/linux/device/driver.h:262:1: note: in expansion of macro 'module_init'
262 | module_init(__driver##_init); \
| ^~~~~~~~~~~
include/linux/i3c/device.h:233:9: note: in expansion of macro 'module_driver'
233 | module_driver(__drv, i3c_driver_register, i3c_driver_unregister)
| ^~~~~~~~~~~~~
drivers/hwmon/tmp108.c:473:1: note: in expansion of macro 'module_i3c_driver'
473 | module_i3c_driver(p3t1085_driver);
| ^~~~~~~~~~~~~~~~~
include/linux/module.h:131:49: note: previous definition of '__inittest' with type 'int (*(void))(void)'
131 | static inline initcall_t __maybe_unused __inittest(void) \
| ^~~~~~~~~~
include/linux/device/driver.h:262:1: note: in expansion of macro 'module_init'
262 | module_init(__driver##_init); \
| ^~~~~~~~~~~
include/linux/i2c.h:965:9: note: in expansion of macro 'module_driver'
965 | module_driver(__i2c_driver, i2c_add_driver, \
| ^~~~~~~~~~~~~
drivers/hwmon/tmp108.c:444:1: note: in expansion of macro 'module_i2c_driver'
444 | module_i2c_driver(tmp108_driver);
| ^~~~~~~~~~~~~~~~~
>> include/linux/module.h:133:13: error: redefinition of 'init_module'
133 | int init_module(void) __copy(initfn) \
| ^~~~~~~~~~~
include/linux/device/driver.h:262:1: note: in expansion of macro 'module_init'
262 | module_init(__driver##_init); \
| ^~~~~~~~~~~
include/linux/i3c/device.h:233:9: note: in expansion of macro 'module_driver'
233 | module_driver(__drv, i3c_driver_register, i3c_driver_unregister)
| ^~~~~~~~~~~~~
drivers/hwmon/tmp108.c:473:1: note: in expansion of macro 'module_i3c_driver'
473 | module_i3c_driver(p3t1085_driver);
| ^~~~~~~~~~~~~~~~~
include/linux/module.h:133:13: note: previous definition of 'init_module' with type 'int(void)'
133 | int init_module(void) __copy(initfn) \
| ^~~~~~~~~~~
include/linux/device/driver.h:262:1: note: in expansion of macro 'module_init'
262 | module_init(__driver##_init); \
| ^~~~~~~~~~~
include/linux/i2c.h:965:9: note: in expansion of macro 'module_driver'
965 | module_driver(__i2c_driver, i2c_add_driver, \
| ^~~~~~~~~~~~~
drivers/hwmon/tmp108.c:444:1: note: in expansion of macro 'module_i2c_driver'
444 | module_i2c_driver(tmp108_driver);
| ^~~~~~~~~~~~~~~~~
>> include/linux/module.h:139:49: error: redefinition of '__exittest'
139 | static inline exitcall_t __maybe_unused __exittest(void) \
| ^~~~~~~~~~
include/linux/device/driver.h:267:1: note: in expansion of macro 'module_exit'
267 | module_exit(__driver##_exit);
| ^~~~~~~~~~~
include/linux/i3c/device.h:233:9: note: in expansion of macro 'module_driver'
233 | module_driver(__drv, i3c_driver_register, i3c_driver_unregister)
| ^~~~~~~~~~~~~
drivers/hwmon/tmp108.c:473:1: note: in expansion of macro 'module_i3c_driver'
473 | module_i3c_driver(p3t1085_driver);
| ^~~~~~~~~~~~~~~~~
include/linux/module.h:139:49: note: previous definition of '__exittest' with type 'void (*(void))(void)'
139 | static inline exitcall_t __maybe_unused __exittest(void) \
| ^~~~~~~~~~
include/linux/device/driver.h:267:1: note: in expansion of macro 'module_exit'
267 | module_exit(__driver##_exit);
| ^~~~~~~~~~~
include/linux/i2c.h:965:9: note: in expansion of macro 'module_driver'
965 | module_driver(__i2c_driver, i2c_add_driver, \
| ^~~~~~~~~~~~~
drivers/hwmon/tmp108.c:444:1: note: in expansion of macro 'module_i2c_driver'
444 | module_i2c_driver(tmp108_driver);
| ^~~~~~~~~~~~~~~~~
>> include/linux/module.h:141:14: error: redefinition of 'cleanup_module'
141 | void cleanup_module(void) __copy(exitfn) \
| ^~~~~~~~~~~~~~
include/linux/device/driver.h:267:1: note: in expansion of macro 'module_exit'
267 | module_exit(__driver##_exit);
| ^~~~~~~~~~~
include/linux/i3c/device.h:233:9: note: in expansion of macro 'module_driver'
233 | module_driver(__drv, i3c_driver_register, i3c_driver_unregister)
| ^~~~~~~~~~~~~
drivers/hwmon/tmp108.c:473:1: note: in expansion of macro 'module_i3c_driver'
473 | module_i3c_driver(p3t1085_driver);
| ^~~~~~~~~~~~~~~~~
include/linux/module.h:141:14: note: previous definition of 'cleanup_module' with type 'void(void)'
141 | void cleanup_module(void) __copy(exitfn) \
| ^~~~~~~~~~~~~~
include/linux/device/driver.h:267:1: note: in expansion of macro 'module_exit'
267 | module_exit(__driver##_exit);
| ^~~~~~~~~~~
include/linux/i2c.h:965:9: note: in expansion of macro 'module_driver'
965 | module_driver(__i2c_driver, i2c_add_driver, \
| ^~~~~~~~~~~~~
drivers/hwmon/tmp108.c:444:1: note: in expansion of macro 'module_i2c_driver'
444 | module_i2c_driver(tmp108_driver);
| ^~~~~~~~~~~~~~~~~
vim +/__inittest +131 include/linux/module.h
0fd972a7d91d6e1 Paul Gortmaker 2015-05-01 128
0fd972a7d91d6e1 Paul Gortmaker 2015-05-01 129 /* Each module must use one module_init(). */
0fd972a7d91d6e1 Paul Gortmaker 2015-05-01 130 #define module_init(initfn) \
1f318a8bafcfba9 Arnd Bergmann 2017-02-01 @131 static inline initcall_t __maybe_unused __inittest(void) \
0fd972a7d91d6e1 Paul Gortmaker 2015-05-01 132 { return initfn; } \
cf68fffb66d60d9 Sami Tolvanen 2021-04-08 @133 int init_module(void) __copy(initfn) \
cf68fffb66d60d9 Sami Tolvanen 2021-04-08 134 __attribute__((alias(#initfn))); \
92efda8eb15295a Sami Tolvanen 2022-09-08 135 ___ADDRESSABLE(init_module, __initdata);
0fd972a7d91d6e1 Paul Gortmaker 2015-05-01 136
0fd972a7d91d6e1 Paul Gortmaker 2015-05-01 137 /* This is only required if you want to be unloadable. */
0fd972a7d91d6e1 Paul Gortmaker 2015-05-01 138 #define module_exit(exitfn) \
1f318a8bafcfba9 Arnd Bergmann 2017-02-01 @139 static inline exitcall_t __maybe_unused __exittest(void) \
0fd972a7d91d6e1 Paul Gortmaker 2015-05-01 140 { return exitfn; } \
cf68fffb66d60d9 Sami Tolvanen 2021-04-08 @141 void cleanup_module(void) __copy(exitfn) \
cf68fffb66d60d9 Sami Tolvanen 2021-04-08 142 __attribute__((alias(#exitfn))); \
92efda8eb15295a Sami Tolvanen 2022-09-08 143 ___ADDRESSABLE(cleanup_module, __exitdata);
0fd972a7d91d6e1 Paul Gortmaker 2015-05-01 144
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
On 11/11/24 09:32, Frank Li wrote:
> Add support for I3C device in the tmp108 driver to handle the P3T1085
> sensor. Register the I3C device driver to enable I3C functionality for the
> sensor.
>
> Signed-off-by: Frank Li <Frank.Li@nxp.com>
> ---
> change from v2 to v3
> - change kconfig to select REGMAP_I3C if enable i3c
> - remove i3c/master.h
> - remove , after {}
> - use #ifdef CONFIG_I3C about i3c register code
>
> I2C I3C
> Y Y support both
> Y N i3c part code will not be compiled
> N Y whole TPM108 will not be compiled
> N N whole TPM108 will not be compiled
> ---
> drivers/hwmon/Kconfig | 1 +
> drivers/hwmon/tmp108.c | 31 +++++++++++++++++++++++++++++++
> 2 files changed, 32 insertions(+)
>
> diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
> index d43ca7aa4a548..9579db7849e1f 100644
> --- a/drivers/hwmon/Kconfig
> +++ b/drivers/hwmon/Kconfig
> @@ -2298,6 +2298,7 @@ config SENSORS_TMP108
> tristate "Texas Instruments TMP108"
> depends on I2C
> select REGMAP_I2C
> + select REGMAP_I3C if I3C
> help
> If you say yes here you get support for Texas Instruments TMP108
> sensor chips and NXP P3T1085.
> diff --git a/drivers/hwmon/tmp108.c b/drivers/hwmon/tmp108.c
> index bfbea6349a95f..deb1505321335 100644
> --- a/drivers/hwmon/tmp108.c
> +++ b/drivers/hwmon/tmp108.c
> @@ -13,6 +13,7 @@
> #include <linux/mutex.h>
> #include <linux/of.h>
> #include <linux/i2c.h>
> +#include <linux/i3c/device.h>
> #include <linux/init.h>
> #include <linux/jiffies.h>
> #include <linux/regmap.h>
> @@ -442,6 +443,36 @@ static struct i2c_driver tmp108_driver = {
>
> module_i2c_driver(tmp108_driver);
>
> +#ifdef CONFIG_I3C
> +static const struct i3c_device_id p3t1085_i3c_ids[] = {
> + I3C_DEVICE(0x011b, 0x1529, NULL),
> + {}
> +};
> +MODULE_DEVICE_TABLE(i3c, p3t1085_i3c_ids);
> +
> +static int p3t1085_i3c_probe(struct i3c_device *i3cdev)
> +{
> + struct device *dev = i3cdev_to_dev(i3cdev);
> + struct regmap *regmap;
> +
> + regmap = devm_regmap_init_i3c(i3cdev, &tmp108_regmap_config);
It is a bit kludgy, but maybe
#ifdef REGMAP_I3C
regmap = devm_regmap_init_i3c(i3cdev, &tmp108_regmap_config);
#else
regmap = ERR_PTR(-ENODEV);
#endif
and then using module_i3c_i2c_driver() would work.
Guenter
> + if (IS_ERR(regmap))
> + return dev_err_probe(dev, PTR_ERR(regmap),
> + "Failed to register i3c regmap\n");
> +
> + return tmp108_common_probe(dev, regmap, "p3t1085_i3c");
> +}
> +
> +static struct i3c_driver p3t1085_driver = {
> + .driver = {
> + .name = "p3t1085_i3c",
> + },
> + .probe = p3t1085_i3c_probe,
> + .id_table = p3t1085_i3c_ids,
> +};
> +module_i3c_driver(p3t1085_driver);
> +#endif
> +
> MODULE_AUTHOR("John Muir <john@jmuir.com>");
> MODULE_DESCRIPTION("Texas Instruments TMP108 temperature sensor driver");
> MODULE_LICENSE("GPL");
>
On 11/11/24 09:32, Frank Li wrote:
> Add support for I3C device in the tmp108 driver to handle the P3T1085
> sensor. Register the I3C device driver to enable I3C functionality for the
> sensor.
>
> Signed-off-by: Frank Li <Frank.Li@nxp.com>
> ---
> change from v2 to v3
> - change kconfig to select REGMAP_I3C if enable i3c
> - remove i3c/master.h
> - remove , after {}
> - use #ifdef CONFIG_I3C about i3c register code
>
> I2C I3C
> Y Y support both
> Y N i3c part code will not be compiled
> N Y whole TPM108 will not be compiled
> N N whole TPM108 will not be compiled
> ---
> drivers/hwmon/Kconfig | 1 +
> drivers/hwmon/tmp108.c | 31 +++++++++++++++++++++++++++++++
> 2 files changed, 32 insertions(+)
>
> diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
> index d43ca7aa4a548..9579db7849e1f 100644
> --- a/drivers/hwmon/Kconfig
> +++ b/drivers/hwmon/Kconfig
> @@ -2298,6 +2298,7 @@ config SENSORS_TMP108
> tristate "Texas Instruments TMP108"
> depends on I2C
> select REGMAP_I2C
> + select REGMAP_I3C if I3C
> help
> If you say yes here you get support for Texas Instruments TMP108
> sensor chips and NXP P3T1085.
> diff --git a/drivers/hwmon/tmp108.c b/drivers/hwmon/tmp108.c
> index bfbea6349a95f..deb1505321335 100644
> --- a/drivers/hwmon/tmp108.c
> +++ b/drivers/hwmon/tmp108.c
> @@ -13,6 +13,7 @@
> #include <linux/mutex.h>
> #include <linux/of.h>
> #include <linux/i2c.h>
> +#include <linux/i3c/device.h>
> #include <linux/init.h>
> #include <linux/jiffies.h>
> #include <linux/regmap.h>
> @@ -442,6 +443,36 @@ static struct i2c_driver tmp108_driver = {
>
> module_i2c_driver(tmp108_driver);
>
> +#ifdef CONFIG_I3C
> +static const struct i3c_device_id p3t1085_i3c_ids[] = {
> + I3C_DEVICE(0x011b, 0x1529, NULL),
> + {}
> +};
> +MODULE_DEVICE_TABLE(i3c, p3t1085_i3c_ids);
> +
> +static int p3t1085_i3c_probe(struct i3c_device *i3cdev)
> +{
> + struct device *dev = i3cdev_to_dev(i3cdev);
> + struct regmap *regmap;
> +
> + regmap = devm_regmap_init_i3c(i3cdev, &tmp108_regmap_config);
> + if (IS_ERR(regmap))
> + return dev_err_probe(dev, PTR_ERR(regmap),
> + "Failed to register i3c regmap\n");
> +
> + return tmp108_common_probe(dev, regmap, "p3t1085_i3c");
> +}
> +
> +static struct i3c_driver p3t1085_driver = {
> + .driver = {
> + .name = "p3t1085_i3c",
> + },
> + .probe = p3t1085_i3c_probe,
> + .id_table = p3t1085_i3c_ids,
> +};
> +module_i3c_driver(p3t1085_driver);
> +#endif
While looking at i3c code, I found module_i3c_i2c_driver(). Can we use
that function to register both i2c and i3c in one call ?
Thanks,
Guenter
On 11/11/24 10:04, Guenter Roeck wrote:
[ ... ]
>> +static int p3t1085_i3c_probe(struct i3c_device *i3cdev)
>> +{
>> + struct device *dev = i3cdev_to_dev(i3cdev);
>> + struct regmap *regmap;
>> +
>> + regmap = devm_regmap_init_i3c(i3cdev, &tmp108_regmap_config);
>> + if (IS_ERR(regmap))
>> + return dev_err_probe(dev, PTR_ERR(regmap),
>> + "Failed to register i3c regmap\n");
>> +
>> + return tmp108_common_probe(dev, regmap, "p3t1085_i3c");
>> +}
>> +
>> +static struct i3c_driver p3t1085_driver = {
>> + .driver = {
>> + .name = "p3t1085_i3c",
>> + },
>> + .probe = p3t1085_i3c_probe,
>> + .id_table = p3t1085_i3c_ids,
>> +};
>> +module_i3c_driver(p3t1085_driver);
>> +#endif
>
> While looking at i3c code, I found module_i3c_i2c_driver(). Can we use
> that function to register both i2c and i3c in one call ?
>
Answering my own question: No, because devm_regmap_init_i3c()
does not provide a dummy function if i3C is not enabled.
Guenter
On 11/11/24 10:10, Guenter Roeck wrote:
> On 11/11/24 10:04, Guenter Roeck wrote:
> [ ... ]
>>> +static int p3t1085_i3c_probe(struct i3c_device *i3cdev)
>>> +{
>>> + struct device *dev = i3cdev_to_dev(i3cdev);
>>> + struct regmap *regmap;
>>> +
>>> + regmap = devm_regmap_init_i3c(i3cdev, &tmp108_regmap_config);
>>> + if (IS_ERR(regmap))
>>> + return dev_err_probe(dev, PTR_ERR(regmap),
>>> + "Failed to register i3c regmap\n");
>>> +
>>> + return tmp108_common_probe(dev, regmap, "p3t1085_i3c");
>>> +}
>>> +
>>> +static struct i3c_driver p3t1085_driver = {
>>> + .driver = {
>>> + .name = "p3t1085_i3c",
>>> + },
>>> + .probe = p3t1085_i3c_probe,
>>> + .id_table = p3t1085_i3c_ids,
>>> +};
>>> +module_i3c_driver(p3t1085_driver);
>>> +#endif
>>
>> While looking at i3c code, I found module_i3c_i2c_driver(). Can we use
>> that function to register both i2c and i3c in one call ?
>>
> Answering my own question: No, because devm_regmap_init_i3c()
> does not provide a dummy function if i3C is not enabled.
>
I do have another concern, though: What happens if the i2c part of the driver
registers and the i3c part fails to register ? module_i3c_i2c_driver() handles
that situation by unregistering the i2c driver, but I don't really know
what happens if a single module registers two drivers and one of them fails.
Thanks,
Guenter
On Mon, Nov 11, 2024 at 10:37:04AM -0800, Guenter Roeck wrote:
> On 11/11/24 10:10, Guenter Roeck wrote:
> > On 11/11/24 10:04, Guenter Roeck wrote:
> > [ ... ]
> > > > +static int p3t1085_i3c_probe(struct i3c_device *i3cdev)
> > > > +{
> > > > + struct device *dev = i3cdev_to_dev(i3cdev);
> > > > + struct regmap *regmap;
> > > > +
> > > > + regmap = devm_regmap_init_i3c(i3cdev, &tmp108_regmap_config);
> > > > + if (IS_ERR(regmap))
> > > > + return dev_err_probe(dev, PTR_ERR(regmap),
> > > > + "Failed to register i3c regmap\n");
> > > > +
> > > > + return tmp108_common_probe(dev, regmap, "p3t1085_i3c");
> > > > +}
> > > > +
> > > > +static struct i3c_driver p3t1085_driver = {
> > > > + .driver = {
> > > > + .name = "p3t1085_i3c",
> > > > + },
> > > > + .probe = p3t1085_i3c_probe,
> > > > + .id_table = p3t1085_i3c_ids,
> > > > +};
> > > > +module_i3c_driver(p3t1085_driver);
> > > > +#endif
> > >
> > > While looking at i3c code, I found module_i3c_i2c_driver(). Can we use
> > > that function to register both i2c and i3c in one call ?
> > >
> > Answering my own question: No, because devm_regmap_init_i3c()
> > does not provide a dummy function if i3C is not enabled.
> >
>
> I do have another concern, though: What happens if the i2c part of the driver
> registers and the i3c part fails to register ? module_i3c_i2c_driver() handles
> that situation by unregistering the i2c driver, but I don't really know
> what happens if a single module registers two drivers and one of them fails.
After use module_i3c_i2c_driver(), and remove #ifdef I3C, and disable I3C
in config, build passed.
It possible cause by
static inline int i3c_i2c_driver_register(struct i3c_driver *i3cdrv,
struct i2c_driver *i2cdrv)
{
int ret;
ret = i2c_add_driver(i2cdrv);
if (ret || !IS_ENABLED(CONFIG_I3C))
return ret;
^^^ !IS_ENABLED(CONFIG_I3C) is true, so linker skip below part. So no
ref to i3cdrv, so linker remove all related codes.
I use aarch64-linux-gnu-gcc (Ubuntu 11.4.0-1ubuntu1~22.04) 11.4.0.
Did you met error if use module_i3c_i2c_driver()?
ret = i3c_driver_register(i3cdrv);
if (ret)
i2c_del_driver(i2cdrv);
return ret;
}
>
> Thanks,
> Guenter
>
On 11/11/24 15:20, Frank Li wrote:
> On Mon, Nov 11, 2024 at 10:37:04AM -0800, Guenter Roeck wrote:
>> On 11/11/24 10:10, Guenter Roeck wrote:
>>> On 11/11/24 10:04, Guenter Roeck wrote:
>>> [ ... ]
>>>>> +static int p3t1085_i3c_probe(struct i3c_device *i3cdev)
>>>>> +{
>>>>> + struct device *dev = i3cdev_to_dev(i3cdev);
>>>>> + struct regmap *regmap;
>>>>> +
>>>>> + regmap = devm_regmap_init_i3c(i3cdev, &tmp108_regmap_config);
>>>>> + if (IS_ERR(regmap))
>>>>> + return dev_err_probe(dev, PTR_ERR(regmap),
>>>>> + "Failed to register i3c regmap\n");
>>>>> +
>>>>> + return tmp108_common_probe(dev, regmap, "p3t1085_i3c");
>>>>> +}
>>>>> +
>>>>> +static struct i3c_driver p3t1085_driver = {
>>>>> + .driver = {
>>>>> + .name = "p3t1085_i3c",
>>>>> + },
>>>>> + .probe = p3t1085_i3c_probe,
>>>>> + .id_table = p3t1085_i3c_ids,
>>>>> +};
>>>>> +module_i3c_driver(p3t1085_driver);
>>>>> +#endif
>>>>
>>>> While looking at i3c code, I found module_i3c_i2c_driver(). Can we use
>>>> that function to register both i2c and i3c in one call ?
>>>>
>>> Answering my own question: No, because devm_regmap_init_i3c()
>>> does not provide a dummy function if i3C is not enabled.
>>>
>>
>> I do have another concern, though: What happens if the i2c part of the driver
>> registers and the i3c part fails to register ? module_i3c_i2c_driver() handles
>> that situation by unregistering the i2c driver, but I don't really know
>> what happens if a single module registers two drivers and one of them fails.
>
> After use module_i3c_i2c_driver(), and remove #ifdef I3C, and disable I3C
> in config, build passed.
>
> It possible cause by
>
> static inline int i3c_i2c_driver_register(struct i3c_driver *i3cdrv,
> struct i2c_driver *i2cdrv)
> {
> int ret;
>
> ret = i2c_add_driver(i2cdrv);
> if (ret || !IS_ENABLED(CONFIG_I3C))
> return ret;
>
> ^^^ !IS_ENABLED(CONFIG_I3C) is true, so linker skip below part. So no
> ref to i3cdrv, so linker remove all related codes.
>
Yes, but I don't think we can rely on the compiler removing the call to
devm_regmap_init_i3c().
Thanks,
Guenter
© 2016 - 2026 Red Hat, Inc.