* [PATCH v4 1/3] dt-bindings: hwmon: ti,tmp108: Add P3T1035,P3T2030
@ 2026-01-16 11:35 Mayank Mahajan
2026-01-16 11:35 ` [PATCH v4 2/3] hwmon: (tmp108) Add support for P3T1035 and P3T2030 Mayank Mahajan
` (2 more replies)
0 siblings, 3 replies; 9+ messages in thread
From: Mayank Mahajan @ 2026-01-16 11:35 UTC (permalink / raw)
To: linux, corbet, robh, krzk+dt, conor+dt, linux-hwmon, devicetree,
linux-doc, linux-kernel
Cc: priyanka.jain, vikash.bansal, Mayank Mahajan
Document the NXP P3T1035 and P3T2030 compatibles in TMP108.
Signed-off-by: Mayank Mahajan <mayankmahajan.x@nxp.com>
---
V1 -> V2:
- No changes in v2.
V2 -> V3:
- Add P3T1035 fallback for P3T2030 as they are functionally identical.
- Add comment in the description explaining the use of P3T2030.
V3 -> V4:
- Remove comment in the description explaining the schema.
.../devicetree/bindings/hwmon/ti,tmp108.yaml | 21 ++++++++++++-------
1 file changed, 13 insertions(+), 8 deletions(-)
diff --git a/Documentation/devicetree/bindings/hwmon/ti,tmp108.yaml b/Documentation/devicetree/bindings/hwmon/ti,tmp108.yaml
index a6f9319e068d..9f6c9f6fa561 100644
--- a/Documentation/devicetree/bindings/hwmon/ti,tmp108.yaml
+++ b/Documentation/devicetree/bindings/hwmon/ti,tmp108.yaml
@@ -4,27 +4,32 @@
$id: http://devicetree.org/schemas/hwmon/ti,tmp108.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
-title: TMP108/P3T1085(NXP) temperature sensor
+title: TMP108/P3T1035/P3T1085/P3T2030 temperature sensor
maintainers:
- Krzysztof Kozlowski <krzk@kernel.org>
description: |
- The TMP108/P3T1085(NXP) is a digital-output temperature sensor with a
- dynamically-programmable limit window, and under- and overtemperature
- alert functions.
+ The TMP108 or NXP P3T Family (P3T1035, P3T1085 and P3T2030) is a digital-
+ output temperature sensor with a dynamically-programmable limit window,
+ and under- and over-temperature alert functions.
- P3T1085(NXP) support I3C.
+ NXP P3T Family (P3T1035, P3T1085 and P3T2030) supports I3C.
Datasheets:
https://www.ti.com/product/TMP108
https://www.nxp.com/docs/en/data-sheet/P3T1085UK.pdf
+ https://www.nxp.com/docs/en/data-sheet/P3T1035XUK_P3T2030XUK.pdf
properties:
compatible:
- enum:
- - nxp,p3t1085
- - ti,tmp108
+ oneOf:
+ - items:
+ - const: nxp,p3t2030
+ - const: nxp,p3t1035
+ - const: nxp,p3t1035
+ - const: nxp,p3t1085
+ - const: ti,tmp108
interrupts:
items:
base-commit: 983d014aafb14ee5e4915465bf8948e8f3a723b5
--
2.34.1
^ permalink raw reply [flat|nested] 9+ messages in thread* [PATCH v4 2/3] hwmon: (tmp108) Add support for P3T1035 and P3T2030 2026-01-16 11:35 [PATCH v4 1/3] dt-bindings: hwmon: ti,tmp108: Add P3T1035,P3T2030 Mayank Mahajan @ 2026-01-16 11:35 ` Mayank Mahajan 2026-01-16 21:37 ` kernel test robot 2026-01-16 22:28 ` Frank Li 2026-01-16 11:35 ` [PATCH v4 3/3] hwmon: (tmp108) Add P3T1035 and P3T2030 support Mayank Mahajan 2026-01-16 14:38 ` [PATCH v4 1/3] dt-bindings: hwmon: ti,tmp108: Add P3T1035,P3T2030 Krzysztof Kozlowski 2 siblings, 2 replies; 9+ messages in thread From: Mayank Mahajan @ 2026-01-16 11:35 UTC (permalink / raw) To: linux, corbet, robh, krzk+dt, conor+dt, linux-hwmon, devicetree, linux-doc, linux-kernel Cc: priyanka.jain, vikash.bansal, Mayank Mahajan Add support for the P3T1035 & P3T2030 temperature sensor. While mostly compatible with the TMP108, P3T1035 uses an 8-bit configuration register instead of the 16-bit layout used by TMP108. Updated driver to handle this difference during configuration read/write. Signed-off-by: Mayank Mahajan <mayankmahajan.x@nxp.com> --- V1 -> V2: - Disabled hysteresis in is_visible function for P3T1035. - Added tables for conversion rate similar to the LM75 driver. - Implemented different bus access depending on the chip being used. - Removed regmap for 8 bits; now we are using one regmap as before. - Added read and write functions for i2c and i3c for use with regmap. - Mapped the 8-bit configuration register to a 16 bit value for P3T1035. V2 -> V3: - Remove changes not relevant to adding a new device in the driver. - Address warnings due to incorrect usage of casting operations. - Remove the usage of P3T2030 as it's functionally identical to P3T1035. V3 -> V4: - Add GENMASK for getting mask for conversion rates. - Add static arrays for containing sample times for different sensors. - Remove redundant code such as checking for NULL pointer in probe. - Improve readability by removing double negation. - Remove type cast where not required; make reg_buf & val_buf local. drivers/hwmon/Kconfig | 2 +- drivers/hwmon/tmp108.c | 203 +++++++++++++++++++++++++++++++++-------- 2 files changed, 164 insertions(+), 41 deletions(-) diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig index 157678b821fc..31969bddc812 100644 --- a/drivers/hwmon/Kconfig +++ b/drivers/hwmon/Kconfig @@ -2398,7 +2398,7 @@ config SENSORS_TMP108 select REGMAP_I3C if I3C help If you say yes here you get support for Texas Instruments TMP108 - sensor chips and NXP P3T1085. + sensor chips, NXP temperature sensors P3T1035, P3T1085 and P3T2030. This driver can also be built as a module. If so, the module will be called tmp108. diff --git a/drivers/hwmon/tmp108.c b/drivers/hwmon/tmp108.c index 60a237cbedbc..d308e2aed18a 100644 --- a/drivers/hwmon/tmp108.c +++ b/drivers/hwmon/tmp108.c @@ -17,9 +17,16 @@ #include <linux/regmap.h> #include <linux/regulator/consumer.h> #include <linux/slab.h> +#include <linux/util_macros.h> #define DRIVER_NAME "tmp108" +enum tmp108_hw_id { + P3T1035_ID, /* For sensors p3t1035 and p3t2030 */ + P3T1085_ID, + TMP108_ID, +}; + #define TMP108_REG_TEMP 0x00 #define TMP108_REG_CONF 0x01 #define TMP108_REG_TLOW 0x02 @@ -61,6 +68,7 @@ #define TMP108_CONVRATE_1HZ TMP108_CONF_CR0 /* Default */ #define TMP108_CONVRATE_4HZ TMP108_CONF_CR1 #define TMP108_CONVRATE_16HZ (TMP108_CONF_CR0|TMP108_CONF_CR1) +#define TMP108_CONVRATE_SHIFT 13 #define TMP108_CONF_HYSTERESIS_MASK (TMP108_CONF_HYS0|TMP108_CONF_HYS1) #define TMP108_HYSTERESIS_0C 0x0000 @@ -70,12 +78,23 @@ #define TMP108_CONVERSION_TIME_MS 30 /* in milli-seconds */ +#define TMP108_CONF_CR0_POS 13 +#define TMP108_CONF_CR1_POS 14 +#define TMP108_CONF_CONVRATE_FLD GENMASK(TMP108_CONF_CR1_POS, TMP108_CONF_CR0_POS) + struct tmp108 { - struct regmap *regmap; - u16 orig_config; - unsigned long ready_time; + struct regmap *regmap; + u16 orig_config; + unsigned long ready_time; + enum tmp108_hw_id hw_id; + bool config_reg_16bits; + ushort *sample_times; + size_t n_sample_times; }; +ushort p3t1035_sample_times[] = {4000, 1000, 250, 125}; +ushort tmp108_sample_times[] = {4000, 1000, 250, 63}; + /* convert 12-bit TMP108 register value to milliCelsius */ static inline int tmp108_temp_reg_to_mC(s16 val) { @@ -101,21 +120,7 @@ static int tmp108_read(struct device *dev, enum hwmon_sensor_types type, ®val); if (err < 0) return err; - switch (regval & TMP108_CONF_CONVRATE_MASK) { - case TMP108_CONVRATE_0P25HZ: - default: - *temp = 4000; - break; - case TMP108_CONVRATE_1HZ: - *temp = 1000; - break; - case TMP108_CONVRATE_4HZ: - *temp = 250; - break; - case TMP108_CONVRATE_16HZ: - *temp = 63; - break; - } + *temp = tmp108->sample_times[FIELD_GET(TMP108_CONF_CONVRATE_FLD, regval)]; return 0; } return -EOPNOTSUPP; @@ -192,22 +197,17 @@ static int tmp108_write(struct device *dev, enum hwmon_sensor_types type, { struct tmp108 *tmp108 = dev_get_drvdata(dev); u32 regval, mask; + u8 index; int err; if (type == hwmon_chip) { if (attr == hwmon_chip_update_interval) { - if (temp < 156) - mask = TMP108_CONVRATE_16HZ; - else if (temp < 625) - mask = TMP108_CONVRATE_4HZ; - else if (temp < 2500) - mask = TMP108_CONVRATE_1HZ; - else - mask = TMP108_CONVRATE_0P25HZ; + index = find_closest_descending(temp, tmp108->sample_times, + tmp108->n_sample_times); return regmap_update_bits(tmp108->regmap, TMP108_REG_CONF, TMP108_CONF_CONVRATE_MASK, - mask); + FIELD_PREP(TMP108_CONF_CONVRATE_FLD, index)); } return -EOPNOTSUPP; } @@ -251,6 +251,8 @@ static int tmp108_write(struct device *dev, enum hwmon_sensor_types type, static umode_t tmp108_is_visible(const void *data, enum hwmon_sensor_types type, u32 attr, int channel) { + const struct tmp108 *tmp108 = data; + if (type == hwmon_chip && attr == hwmon_chip_update_interval) return 0644; @@ -264,8 +266,11 @@ static umode_t tmp108_is_visible(const void *data, enum hwmon_sensor_types type, return 0444; case hwmon_temp_min: case hwmon_temp_max: + return 0644; case hwmon_temp_min_hyst: case hwmon_temp_max_hyst: + if (tmp108->hw_id == P3T1035_ID) + return 0; return 0644; default: return 0; @@ -311,6 +316,106 @@ static bool tmp108_is_volatile_reg(struct device *dev, unsigned int reg) return reg == TMP108_REG_TEMP || reg == TMP108_REG_CONF; } +static int tmp108_i2c_reg_read(void *context, unsigned int reg, unsigned int *val) +{ + struct i2c_client *client = context; + struct tmp108 *tmp108 = i2c_get_clientdata(client); + int ret; + + if (reg == TMP108_REG_CONF && !tmp108->config_reg_16bits) { + ret = i2c_smbus_read_byte_data(client, TMP108_REG_CONF); + if (ret < 0) + return ret; + *val = ret << 8; + return 0; + } + + ret = i2c_smbus_read_word_swapped(client, reg); + if (ret < 0) + return ret; + *val = ret; + return 0; +} + +static int tmp108_i2c_reg_write(void *context, unsigned int reg, unsigned int val) +{ + struct i2c_client *client = context; + struct tmp108 *tmp108 = i2c_get_clientdata(client); + + if (reg == TMP108_REG_CONF && !tmp108->config_reg_16bits) + return i2c_smbus_write_byte_data(client, reg, val >> 8); + return i2c_smbus_write_word_swapped(client, reg, val); +} + +static const struct regmap_bus tmp108_i2c_regmap_bus = { + .reg_read = tmp108_i2c_reg_read, + .reg_write = tmp108_i2c_reg_write, +}; + +static int tmp108_i3c_reg_read(void *context, unsigned int reg, unsigned int *val) +{ + struct i3c_device *i3cdev = context; + struct tmp108 *tmp108 = i3cdev_get_drvdata(i3cdev); + u8 reg_buf[1], val_buf[2]; + struct i3c_xfer xfers[] = { + { + .rnw = false, + .len = 1, + .data.out = reg_buf, + }, + { + .rnw = true, + .len = 2, + .data.in = val_buf, + }, + }; + int ret; + + reg_buf[0] = reg; + + if (reg == TMP108_REG_CONF && !tmp108->config_reg_16bits) + xfers[1].len--; + + ret = i3c_device_do_xfers(i3cdev, xfers, 2, I3C_SDR); + if (ret < 0) + return ret; + + *val = val_buf[0] << 8; + if (reg != TMP108_REG_CONF || tmp108->config_reg_16bits) + *val |= val_buf[1]; + + return 0; +} + +static int tmp108_i3c_reg_write(void *context, unsigned int reg, unsigned int val) +{ + struct i3c_device *i3cdev = context; + struct tmp108 *tmp108 = i3cdev_get_drvdata(i3cdev); + u8 val_buf[3]; + struct i3c_xfer xfers[] = { + { + .rnw = false, + .len = 3, + .data.out = val_buf, + }, + }; + + val_buf[0] = reg; + val_buf[1] = (val >> 8) & 0xff; + + if (reg == TMP108_REG_CONF && !tmp108->config_reg_16bits) + xfers[0].len--; + else + val_buf[2] = val & 0xff; + + return i3c_device_do_xfers(i3cdev, xfers, 1, I3C_SDR); +} + +static const struct regmap_bus tmp108_i3c_regmap_bus = { + .reg_read = tmp108_i3c_reg_read, + .reg_write = tmp108_i3c_reg_write, +}; + static const struct regmap_config tmp108_regmap_config = { .reg_bits = 8, .val_bits = 16, @@ -323,7 +428,8 @@ static const struct regmap_config tmp108_regmap_config = { .use_single_write = true, }; -static int tmp108_common_probe(struct device *dev, struct regmap *regmap, char *name) +static int tmp108_common_probe(struct device *dev, struct regmap *regmap, char *name, + enum tmp108_hw_id hw_id) { struct device *hwmon_dev; struct tmp108 *tmp108; @@ -340,6 +446,15 @@ static int tmp108_common_probe(struct device *dev, struct regmap *regmap, char * dev_set_drvdata(dev, tmp108); tmp108->regmap = regmap; + tmp108->hw_id = hw_id; + tmp108->config_reg_16bits = (hw_id == P3T1035_ID) ? false : true; + if (hw_id == P3T1035_ID) { + tmp108->sample_times = p3t1035_sample_times; + tmp108->n_sample_times = ARRAY_SIZE(p3t1035_sample_times); + } else { + tmp108->sample_times = tmp108_sample_times; + tmp108->n_sample_times = ARRAY_SIZE(tmp108_sample_times); + } err = regmap_read(tmp108->regmap, TMP108_REG_CONF, &config); if (err < 0) { @@ -351,7 +466,6 @@ static int tmp108_common_probe(struct device *dev, struct regmap *regmap, char * /* Only continuous mode is supported. */ config &= ~TMP108_CONF_MODE_MASK; config |= TMP108_MODE_CONTINUOUS; - /* Only comparator mode is supported. */ config &= ~TMP108_CONF_TM; @@ -384,17 +498,20 @@ static int tmp108_probe(struct i2c_client *client) { struct device *dev = &client->dev; struct regmap *regmap; + enum tmp108_hw_id hw_id; if (!i2c_check_functionality(client->adapter, - I2C_FUNC_SMBUS_WORD_DATA)) + I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA)) return dev_err_probe(dev, -ENODEV, "adapter doesn't support SMBus word transactions\n"); - regmap = devm_regmap_init_i2c(client, &tmp108_regmap_config); + regmap = devm_regmap_init(dev, &tmp108_i2c_regmap_bus, client, &tmp108_regmap_config); if (IS_ERR(regmap)) return dev_err_probe(dev, PTR_ERR(regmap), "regmap init failed"); - return tmp108_common_probe(dev, regmap, client->name); + hw_id = (unsigned long)i2c_get_match_data(client); + + return tmp108_common_probe(dev, regmap, client->name, hw_id); } static int tmp108_suspend(struct device *dev) @@ -420,15 +537,17 @@ static int tmp108_resume(struct device *dev) static DEFINE_SIMPLE_DEV_PM_OPS(tmp108_dev_pm_ops, tmp108_suspend, tmp108_resume); static const struct i2c_device_id tmp108_i2c_ids[] = { - { "p3t1085" }, - { "tmp108" }, - { } + { "p3t1035", P3T1035_ID }, + { "p3t1085", P3T1085_ID }, + { "tmp108", TMP108_ID }, + {} }; MODULE_DEVICE_TABLE(i2c, tmp108_i2c_ids); static const struct of_device_id tmp108_of_ids[] = { - { .compatible = "nxp,p3t1085", }, - { .compatible = "ti,tmp108", }, + { .compatible = "nxp,p3t1035", .data = (void *)(uintptr_t)P3T1035_ID }, + { .compatible = "nxp,p3t1085", .data = (void *)(uintptr_t)P3T1085_ID }, + { .compatible = "ti,tmp108", .data = (void *)(uintptr_t)TMP108_ID }, {} }; MODULE_DEVICE_TABLE(of, tmp108_of_ids); @@ -444,7 +563,8 @@ static struct i2c_driver tmp108_driver = { }; static const struct i3c_device_id p3t1085_i3c_ids[] = { - I3C_DEVICE(0x011b, 0x1529, NULL), + I3C_DEVICE(0x011B, 0x1529, (void *)P3T1085_ID), + I3C_DEVICE(0x011B, 0x152B, (void *)P3T1035_ID), {} }; MODULE_DEVICE_TABLE(i3c, p3t1085_i3c_ids); @@ -453,13 +573,16 @@ static int p3t1085_i3c_probe(struct i3c_device *i3cdev) { struct device *dev = i3cdev_to_dev(i3cdev); struct regmap *regmap; + const struct i3c_device_id *id; - regmap = devm_regmap_init_i3c(i3cdev, &tmp108_regmap_config); + regmap = devm_regmap_init(dev, &tmp108_i3c_regmap_bus, 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"); + id = i3c_device_match_id(i3cdev, p3t1085_i3c_ids); + + return tmp108_common_probe(dev, regmap, "p3t1085_i3c", (unsigned long)id->data); } static struct i3c_driver p3t1085_driver = { -- 2.34.1 ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH v4 2/3] hwmon: (tmp108) Add support for P3T1035 and P3T2030 2026-01-16 11:35 ` [PATCH v4 2/3] hwmon: (tmp108) Add support for P3T1035 and P3T2030 Mayank Mahajan @ 2026-01-16 21:37 ` kernel test robot 2026-01-16 22:28 ` Frank Li 1 sibling, 0 replies; 9+ messages in thread From: kernel test robot @ 2026-01-16 21:37 UTC (permalink / raw) To: Mayank Mahajan, linux, corbet, robh, krzk+dt, conor+dt, linux-hwmon, devicetree, linux-doc, linux-kernel Cc: llvm, oe-kbuild-all, priyanka.jain, vikash.bansal, Mayank Mahajan Hi Mayank, kernel test robot noticed the following build errors: [auto build test ERROR on 983d014aafb14ee5e4915465bf8948e8f3a723b5] url: https://github.com/intel-lab-lkp/linux/commits/Mayank-Mahajan/hwmon-tmp108-Add-support-for-P3T1035-and-P3T2030/20260116-193800 base: 983d014aafb14ee5e4915465bf8948e8f3a723b5 patch link: https://lore.kernel.org/r/20260116113554.986-2-mayankmahajan.x%40nxp.com patch subject: [PATCH v4 2/3] hwmon: (tmp108) Add support for P3T1035 and P3T2030 config: i386-buildonly-randconfig-004-20260117 (https://download.01.org/0day-ci/archive/20260117/202601170516.uQw9DKHB-lkp@intel.com/config) compiler: clang version 20.1.8 (https://github.com/llvm/llvm-project 87f0227cb60147a26a1eeb4fb06e3b505e9c7261) reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20260117/202601170516.uQw9DKHB-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/202601170516.uQw9DKHB-lkp@intel.com/ All errors (new ones prefixed by >>): >> drivers/hwmon/tmp108.c:123:33: error: call to undeclared function 'FIELD_GET'; ISO C99 and later do not support implicit function declarations [-Wimplicit-function-declaration] 123 | *temp = tmp108->sample_times[FIELD_GET(TMP108_CONF_CONVRATE_FLD, regval)]; | ^ >> drivers/hwmon/tmp108.c:210:9: error: call to undeclared function 'FIELD_PREP'; ISO C99 and later do not support implicit function declarations [-Wimplicit-function-declaration] 210 | FIELD_PREP(TMP108_CONF_CONVRATE_FLD, index)); | ^ 2 errors generated. vim +/FIELD_GET +123 drivers/hwmon/tmp108.c 109 110 static int tmp108_read(struct device *dev, enum hwmon_sensor_types type, 111 u32 attr, int channel, long *temp) 112 { 113 struct tmp108 *tmp108 = dev_get_drvdata(dev); 114 unsigned int regval; 115 int err, hyst; 116 117 if (type == hwmon_chip) { 118 if (attr == hwmon_chip_update_interval) { 119 err = regmap_read(tmp108->regmap, TMP108_REG_CONF, 120 ®val); 121 if (err < 0) 122 return err; > 123 *temp = tmp108->sample_times[FIELD_GET(TMP108_CONF_CONVRATE_FLD, regval)]; 124 return 0; 125 } 126 return -EOPNOTSUPP; 127 } 128 129 switch (attr) { 130 case hwmon_temp_input: 131 /* Is it too early to return a conversion ? */ 132 if (time_before(jiffies, tmp108->ready_time)) { 133 dev_dbg(dev, "%s: Conversion not ready yet..\n", 134 __func__); 135 return -EAGAIN; 136 } 137 err = regmap_read(tmp108->regmap, TMP108_REG_TEMP, ®val); 138 if (err < 0) 139 return err; 140 *temp = tmp108_temp_reg_to_mC(regval); 141 break; 142 case hwmon_temp_min: 143 case hwmon_temp_max: 144 err = regmap_read(tmp108->regmap, attr == hwmon_temp_min ? 145 TMP108_REG_TLOW : TMP108_REG_THIGH, ®val); 146 if (err < 0) 147 return err; 148 *temp = tmp108_temp_reg_to_mC(regval); 149 break; 150 case hwmon_temp_min_alarm: 151 case hwmon_temp_max_alarm: 152 err = regmap_read(tmp108->regmap, TMP108_REG_CONF, ®val); 153 if (err < 0) 154 return err; 155 *temp = !!(regval & (attr == hwmon_temp_min_alarm ? 156 TMP108_CONF_FL : TMP108_CONF_FH)); 157 break; 158 case hwmon_temp_min_hyst: 159 case hwmon_temp_max_hyst: 160 err = regmap_read(tmp108->regmap, TMP108_REG_CONF, ®val); 161 if (err < 0) 162 return err; 163 switch (regval & TMP108_CONF_HYSTERESIS_MASK) { 164 case TMP108_HYSTERESIS_0C: 165 default: 166 hyst = 0; 167 break; 168 case TMP108_HYSTERESIS_1C: 169 hyst = 1000; 170 break; 171 case TMP108_HYSTERESIS_2C: 172 hyst = 2000; 173 break; 174 case TMP108_HYSTERESIS_4C: 175 hyst = 4000; 176 break; 177 } 178 err = regmap_read(tmp108->regmap, attr == hwmon_temp_min_hyst ? 179 TMP108_REG_TLOW : TMP108_REG_THIGH, ®val); 180 if (err < 0) 181 return err; 182 *temp = tmp108_temp_reg_to_mC(regval); 183 if (attr == hwmon_temp_min_hyst) 184 *temp += hyst; 185 else 186 *temp -= hyst; 187 break; 188 default: 189 return -EOPNOTSUPP; 190 } 191 192 return 0; 193 } 194 195 static int tmp108_write(struct device *dev, enum hwmon_sensor_types type, 196 u32 attr, int channel, long temp) 197 { 198 struct tmp108 *tmp108 = dev_get_drvdata(dev); 199 u32 regval, mask; 200 u8 index; 201 int err; 202 203 if (type == hwmon_chip) { 204 if (attr == hwmon_chip_update_interval) { 205 index = find_closest_descending(temp, tmp108->sample_times, 206 tmp108->n_sample_times); 207 return regmap_update_bits(tmp108->regmap, 208 TMP108_REG_CONF, 209 TMP108_CONF_CONVRATE_MASK, > 210 FIELD_PREP(TMP108_CONF_CONVRATE_FLD, index)); 211 } 212 return -EOPNOTSUPP; 213 } 214 215 switch (attr) { 216 case hwmon_temp_min: 217 case hwmon_temp_max: 218 temp = clamp_val(temp, TMP108_TEMP_MIN_MC, TMP108_TEMP_MAX_MC); 219 return regmap_write(tmp108->regmap, 220 attr == hwmon_temp_min ? 221 TMP108_REG_TLOW : TMP108_REG_THIGH, 222 tmp108_mC_to_temp_reg(temp)); 223 case hwmon_temp_min_hyst: 224 case hwmon_temp_max_hyst: 225 temp = clamp_val(temp, TMP108_TEMP_MIN_MC, TMP108_TEMP_MAX_MC); 226 err = regmap_read(tmp108->regmap, 227 attr == hwmon_temp_min_hyst ? 228 TMP108_REG_TLOW : TMP108_REG_THIGH, 229 ®val); 230 if (err < 0) 231 return err; 232 if (attr == hwmon_temp_min_hyst) 233 temp -= tmp108_temp_reg_to_mC(regval); 234 else 235 temp = tmp108_temp_reg_to_mC(regval) - temp; 236 if (temp < 500) 237 mask = TMP108_HYSTERESIS_0C; 238 else if (temp < 1500) 239 mask = TMP108_HYSTERESIS_1C; 240 else if (temp < 3000) 241 mask = TMP108_HYSTERESIS_2C; 242 else 243 mask = TMP108_HYSTERESIS_4C; 244 return regmap_update_bits(tmp108->regmap, TMP108_REG_CONF, 245 TMP108_CONF_HYSTERESIS_MASK, mask); 246 default: 247 return -EOPNOTSUPP; 248 } 249 } 250 -- 0-DAY CI Kernel Test Service https://github.com/intel/lkp-tests/wiki ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH v4 2/3] hwmon: (tmp108) Add support for P3T1035 and P3T2030 2026-01-16 11:35 ` [PATCH v4 2/3] hwmon: (tmp108) Add support for P3T1035 and P3T2030 Mayank Mahajan 2026-01-16 21:37 ` kernel test robot @ 2026-01-16 22:28 ` Frank Li 2026-01-17 0:36 ` Guenter Roeck 1 sibling, 1 reply; 9+ messages in thread From: Frank Li @ 2026-01-16 22:28 UTC (permalink / raw) To: Mayank Mahajan Cc: linux, corbet, robh, krzk+dt, conor+dt, linux-hwmon, devicetree, linux-doc, linux-kernel, priyanka.jain, vikash.bansal On Fri, Jan 16, 2026 at 05:05:53PM +0530, Mayank Mahajan wrote: > Add support for the P3T1035 & P3T2030 temperature sensor. While mostly > compatible with the TMP108, P3T1035 uses an 8-bit configuration register > instead of the 16-bit layout used by TMP108. Updated driver to handle > this difference during configuration read/write. > > Signed-off-by: Mayank Mahajan <mayankmahajan.x@nxp.com> > --- > V1 -> V2: > - Disabled hysteresis in is_visible function for P3T1035. > - Added tables for conversion rate similar to the LM75 driver. > - Implemented different bus access depending on the chip being used. > - Removed regmap for 8 bits; now we are using one regmap as before. > - Added read and write functions for i2c and i3c for use with regmap. > - Mapped the 8-bit configuration register to a 16 bit value for P3T1035. > V2 -> V3: > - Remove changes not relevant to adding a new device in the driver. > - Address warnings due to incorrect usage of casting operations. > - Remove the usage of P3T2030 as it's functionally identical to P3T1035. > V3 -> V4: > - Add GENMASK for getting mask for conversion rates. > - Add static arrays for containing sample times for different sensors. > - Remove redundant code such as checking for NULL pointer in probe. > - Improve readability by removing double negation. > - Remove type cast where not required; make reg_buf & val_buf local. > > drivers/hwmon/Kconfig | 2 +- > drivers/hwmon/tmp108.c | 203 +++++++++++++++++++++++++++++++++-------- > 2 files changed, 164 insertions(+), 41 deletions(-) > > diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig > index 157678b821fc..31969bddc812 100644 > --- a/drivers/hwmon/Kconfig > +++ b/drivers/hwmon/Kconfig > @@ -2398,7 +2398,7 @@ config SENSORS_TMP108 > select REGMAP_I3C if I3C > help > If you say yes here you get support for Texas Instruments TMP108 > - sensor chips and NXP P3T1085. > + sensor chips, NXP temperature sensors P3T1035, P3T1085 and P3T2030. > > This driver can also be built as a module. If so, the module > will be called tmp108. > diff --git a/drivers/hwmon/tmp108.c b/drivers/hwmon/tmp108.c > index 60a237cbedbc..d308e2aed18a 100644 > --- a/drivers/hwmon/tmp108.c > +++ b/drivers/hwmon/tmp108.c > @@ -17,9 +17,16 @@ > #include <linux/regmap.h> > #include <linux/regulator/consumer.h> > #include <linux/slab.h> > +#include <linux/util_macros.h> > > #define DRIVER_NAME "tmp108" > > +enum tmp108_hw_id { > + P3T1035_ID, /* For sensors p3t1035 and p3t2030 */ > + P3T1085_ID, > + TMP108_ID, > +}; > + > #define TMP108_REG_TEMP 0x00 > #define TMP108_REG_CONF 0x01 > #define TMP108_REG_TLOW 0x02 > @@ -61,6 +68,7 @@ > #define TMP108_CONVRATE_1HZ TMP108_CONF_CR0 /* Default */ > #define TMP108_CONVRATE_4HZ TMP108_CONF_CR1 > #define TMP108_CONVRATE_16HZ (TMP108_CONF_CR0|TMP108_CONF_CR1) > +#define TMP108_CONVRATE_SHIFT 13 > > #define TMP108_CONF_HYSTERESIS_MASK (TMP108_CONF_HYS0|TMP108_CONF_HYS1) > #define TMP108_HYSTERESIS_0C 0x0000 > @@ -70,12 +78,23 @@ > > #define TMP108_CONVERSION_TIME_MS 30 /* in milli-seconds */ > > +#define TMP108_CONF_CR0_POS 13 > +#define TMP108_CONF_CR1_POS 14 > +#define TMP108_CONF_CONVRATE_FLD GENMASK(TMP108_CONF_CR1_POS, TMP108_CONF_CR0_POS) > + > struct tmp108 { > - struct regmap *regmap; > - u16 orig_config; > - unsigned long ready_time; > + struct regmap *regmap; > + u16 orig_config; > + unsigned long ready_time; don't mix format change in this patch. Now prefer orignial format, just one space between type and field. > + enum tmp108_hw_id hw_id; > + bool config_reg_16bits; > + ushort *sample_times; > + size_t n_sample_times; > }; > > +ushort p3t1035_sample_times[] = {4000, 1000, 250, 125}; > +ushort tmp108_sample_times[] = {4000, 1000, 250, 63}; > + > /* convert 12-bit TMP108 register value to milliCelsius */ > static inline int tmp108_temp_reg_to_mC(s16 val) > { > @@ -101,21 +120,7 @@ static int tmp108_read(struct device *dev, enum hwmon_sensor_types type, > ®val); > if (err < 0) > return err; > - switch (regval & TMP108_CONF_CONVRATE_MASK) { > - case TMP108_CONVRATE_0P25HZ: > - default: > - *temp = 4000; > - break; > - case TMP108_CONVRATE_1HZ: > - *temp = 1000; > - break; > - case TMP108_CONVRATE_4HZ: > - *temp = 250; > - break; > - case TMP108_CONVRATE_16HZ: > - *temp = 63; > - break; > - } > + *temp = tmp108->sample_times[FIELD_GET(TMP108_CONF_CONVRATE_FLD, regval)]; This code optimation need seperate patch. > return 0; > } > return -EOPNOTSUPP; > @@ -192,22 +197,17 @@ static int tmp108_write(struct device *dev, enum hwmon_sensor_types type, > { > struct tmp108 *tmp108 = dev_get_drvdata(dev); > u32 regval, mask; > + u8 index; > int err; > > if (type == hwmon_chip) { > if (attr == hwmon_chip_update_interval) { > - if (temp < 156) > - mask = TMP108_CONVRATE_16HZ; > - else if (temp < 625) > - mask = TMP108_CONVRATE_4HZ; > - else if (temp < 2500) > - mask = TMP108_CONVRATE_1HZ; > - else > - mask = TMP108_CONVRATE_0P25HZ; > + index = find_closest_descending(temp, tmp108->sample_times, > + tmp108->n_sample_times); Need seperate patch for the code cleanup. > return regmap_update_bits(tmp108->regmap, > TMP108_REG_CONF, > TMP108_CONF_CONVRATE_MASK, > - mask); > + FIELD_PREP(TMP108_CONF_CONVRATE_FLD, index)); > } > return -EOPNOTSUPP; > } > @@ -251,6 +251,8 @@ static int tmp108_write(struct device *dev, enum hwmon_sensor_types type, > static umode_t tmp108_is_visible(const void *data, enum hwmon_sensor_types type, > u32 attr, int channel) > { > + const struct tmp108 *tmp108 = data; > + > if (type == hwmon_chip && attr == hwmon_chip_update_interval) > return 0644; > > @@ -264,8 +266,11 @@ static umode_t tmp108_is_visible(const void *data, enum hwmon_sensor_types type, > return 0444; > case hwmon_temp_min: > case hwmon_temp_max: > + return 0644; > case hwmon_temp_min_hyst: > case hwmon_temp_max_hyst: > + if (tmp108->hw_id == P3T1035_ID) > + return 0; > return 0644; > default: > return 0; > @@ -311,6 +316,106 @@ static bool tmp108_is_volatile_reg(struct device *dev, unsigned int reg) > return reg == TMP108_REG_TEMP || reg == TMP108_REG_CONF; > } > > +static int tmp108_i2c_reg_read(void *context, unsigned int reg, unsigned int *val) > +{ > + struct i2c_client *client = context; > + struct tmp108 *tmp108 = i2c_get_clientdata(client); > + int ret; > + > + if (reg == TMP108_REG_CONF && !tmp108->config_reg_16bits) { > + ret = i2c_smbus_read_byte_data(client, TMP108_REG_CONF); > + if (ret < 0) > + return ret; > + *val = ret << 8; > + return 0; > + } > + > + ret = i2c_smbus_read_word_swapped(client, reg); > + if (ret < 0) > + return ret; > + *val = ret; > + return 0; > +} > + > +static int tmp108_i2c_reg_write(void *context, unsigned int reg, unsigned int val) > +{ > + struct i2c_client *client = context; > + struct tmp108 *tmp108 = i2c_get_clientdata(client); > + > + if (reg == TMP108_REG_CONF && !tmp108->config_reg_16bits) > + return i2c_smbus_write_byte_data(client, reg, val >> 8); > + return i2c_smbus_write_word_swapped(client, reg, val); > +} > + > +static const struct regmap_bus tmp108_i2c_regmap_bus = { > + .reg_read = tmp108_i2c_reg_read, > + .reg_write = tmp108_i2c_reg_write, > +}; > + > +static int tmp108_i3c_reg_read(void *context, unsigned int reg, unsigned int *val) > +{ > + struct i3c_device *i3cdev = context; > + struct tmp108 *tmp108 = i3cdev_get_drvdata(i3cdev); > + u8 reg_buf[1], val_buf[2]; > + struct i3c_xfer xfers[] = { > + { > + .rnw = false, > + .len = 1, > + .data.out = reg_buf, > + }, > + { > + .rnw = true, > + .len = 2, > + .data.in = val_buf, > + }, > + }; > + int ret; > + > + reg_buf[0] = reg; > + > + if (reg == TMP108_REG_CONF && !tmp108->config_reg_16bits) > + xfers[1].len--; > + > + ret = i3c_device_do_xfers(i3cdev, xfers, 2, I3C_SDR); > + if (ret < 0) > + return ret; > + > + *val = val_buf[0] << 8; > + if (reg != TMP108_REG_CONF || tmp108->config_reg_16bits) > + *val |= val_buf[1]; > + > + return 0; > +} > + > +static int tmp108_i3c_reg_write(void *context, unsigned int reg, unsigned int val) > +{ > + struct i3c_device *i3cdev = context; > + struct tmp108 *tmp108 = i3cdev_get_drvdata(i3cdev); > + u8 val_buf[3]; > + struct i3c_xfer xfers[] = { > + { > + .rnw = false, > + .len = 3, > + .data.out = val_buf, > + }, > + }; > + > + val_buf[0] = reg; > + val_buf[1] = (val >> 8) & 0xff; > + > + if (reg == TMP108_REG_CONF && !tmp108->config_reg_16bits) > + xfers[0].len--; > + else > + val_buf[2] = val & 0xff; > + > + return i3c_device_do_xfers(i3cdev, xfers, 1, I3C_SDR); > +} > + > +static const struct regmap_bus tmp108_i3c_regmap_bus = { > + .reg_read = tmp108_i3c_reg_read, > + .reg_write = tmp108_i3c_reg_write, > +}; > + > static const struct regmap_config tmp108_regmap_config = { > .reg_bits = 8, > .val_bits = 16, > @@ -323,7 +428,8 @@ static const struct regmap_config tmp108_regmap_config = { > .use_single_write = true, > }; > > -static int tmp108_common_probe(struct device *dev, struct regmap *regmap, char *name) > +static int tmp108_common_probe(struct device *dev, struct regmap *regmap, char *name, > + enum tmp108_hw_id hw_id) > { > struct device *hwmon_dev; > struct tmp108 *tmp108; > @@ -340,6 +446,15 @@ static int tmp108_common_probe(struct device *dev, struct regmap *regmap, char * > > dev_set_drvdata(dev, tmp108); > tmp108->regmap = regmap; > + tmp108->hw_id = hw_id; > + tmp108->config_reg_16bits = (hw_id == P3T1035_ID) ? false : true; > + if (hw_id == P3T1035_ID) { > + tmp108->sample_times = p3t1035_sample_times; > + tmp108->n_sample_times = ARRAY_SIZE(p3t1035_sample_times); > + } else { > + tmp108->sample_times = tmp108_sample_times; > + tmp108->n_sample_times = ARRAY_SIZE(tmp108_sample_times); > + } > > err = regmap_read(tmp108->regmap, TMP108_REG_CONF, &config); > if (err < 0) { > @@ -351,7 +466,6 @@ static int tmp108_common_probe(struct device *dev, struct regmap *regmap, char * > /* Only continuous mode is supported. */ > config &= ~TMP108_CONF_MODE_MASK; > config |= TMP108_MODE_CONTINUOUS; > - > /* Only comparator mode is supported. */ > config &= ~TMP108_CONF_TM; > > @@ -384,17 +498,20 @@ static int tmp108_probe(struct i2c_client *client) > { > struct device *dev = &client->dev; > struct regmap *regmap; > + enum tmp108_hw_id hw_id; > > if (!i2c_check_functionality(client->adapter, > - I2C_FUNC_SMBUS_WORD_DATA)) > + I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA)) > return dev_err_probe(dev, -ENODEV, > "adapter doesn't support SMBus word transactions\n"); > > - regmap = devm_regmap_init_i2c(client, &tmp108_regmap_config); > + regmap = devm_regmap_init(dev, &tmp108_i2c_regmap_bus, client, &tmp108_regmap_config); > if (IS_ERR(regmap)) > return dev_err_probe(dev, PTR_ERR(regmap), "regmap init failed"); > > - return tmp108_common_probe(dev, regmap, client->name); > + hw_id = (unsigned long)i2c_get_match_data(client); > + > + return tmp108_common_probe(dev, regmap, client->name, hw_id); > } > > static int tmp108_suspend(struct device *dev) > @@ -420,15 +537,17 @@ static int tmp108_resume(struct device *dev) > static DEFINE_SIMPLE_DEV_PM_OPS(tmp108_dev_pm_ops, tmp108_suspend, tmp108_resume); > > static const struct i2c_device_id tmp108_i2c_ids[] = { > - { "p3t1085" }, > - { "tmp108" }, > - { } > + { "p3t1035", P3T1035_ID }, > + { "p3t1085", P3T1085_ID }, > + { "tmp108", TMP108_ID }, > + {} > }; > MODULE_DEVICE_TABLE(i2c, tmp108_i2c_ids); > > static const struct of_device_id tmp108_of_ids[] = { > - { .compatible = "nxp,p3t1085", }, > - { .compatible = "ti,tmp108", }, > + { .compatible = "nxp,p3t1035", .data = (void *)(uintptr_t)P3T1035_ID }, > + { .compatible = "nxp,p3t1085", .data = (void *)(uintptr_t)P3T1085_ID }, > + { .compatible = "ti,tmp108", .data = (void *)(uintptr_t)TMP108_ID }, Do not use device ID, define struct drvdata struct tmp108_drvdata { .samples = p3t1035_sample_times; .reg_width = 16, ... } Frank > {} > }; > MODULE_DEVICE_TABLE(of, tmp108_of_ids); > @@ -444,7 +563,8 @@ static struct i2c_driver tmp108_driver = { > }; > > static const struct i3c_device_id p3t1085_i3c_ids[] = { > - I3C_DEVICE(0x011b, 0x1529, NULL), > + I3C_DEVICE(0x011B, 0x1529, (void *)P3T1085_ID), > + I3C_DEVICE(0x011B, 0x152B, (void *)P3T1035_ID), > {} > }; > MODULE_DEVICE_TABLE(i3c, p3t1085_i3c_ids); > @@ -453,13 +573,16 @@ static int p3t1085_i3c_probe(struct i3c_device *i3cdev) > { > struct device *dev = i3cdev_to_dev(i3cdev); > struct regmap *regmap; > + const struct i3c_device_id *id; > > - regmap = devm_regmap_init_i3c(i3cdev, &tmp108_regmap_config); > + regmap = devm_regmap_init(dev, &tmp108_i3c_regmap_bus, 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"); > + id = i3c_device_match_id(i3cdev, p3t1085_i3c_ids); > + > + return tmp108_common_probe(dev, regmap, "p3t1085_i3c", (unsigned long)id->data); > } > > static struct i3c_driver p3t1085_driver = { > -- > 2.34.1 ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH v4 2/3] hwmon: (tmp108) Add support for P3T1035 and P3T2030 2026-01-16 22:28 ` Frank Li @ 2026-01-17 0:36 ` Guenter Roeck 2026-01-18 17:30 ` Frank Li 0 siblings, 1 reply; 9+ messages in thread From: Guenter Roeck @ 2026-01-17 0:36 UTC (permalink / raw) To: Frank Li, Mayank Mahajan Cc: corbet, robh, krzk+dt, conor+dt, linux-hwmon, devicetree, linux-doc, linux-kernel, priyanka.jain, vikash.bansal On 1/16/26 14:28, Frank Li wrote: > On Fri, Jan 16, 2026 at 05:05:53PM +0530, Mayank Mahajan wrote: >> Add support for the P3T1035 & P3T2030 temperature sensor. While mostly >> compatible with the TMP108, P3T1035 uses an 8-bit configuration register >> instead of the 16-bit layout used by TMP108. Updated driver to handle >> this difference during configuration read/write. >> >> Signed-off-by: Mayank Mahajan <mayankmahajan.x@nxp.com> >> --- >> V1 -> V2: >> - Disabled hysteresis in is_visible function for P3T1035. >> - Added tables for conversion rate similar to the LM75 driver. >> - Implemented different bus access depending on the chip being used. >> - Removed regmap for 8 bits; now we are using one regmap as before. >> - Added read and write functions for i2c and i3c for use with regmap. >> - Mapped the 8-bit configuration register to a 16 bit value for P3T1035. >> V2 -> V3: >> - Remove changes not relevant to adding a new device in the driver. >> - Address warnings due to incorrect usage of casting operations. >> - Remove the usage of P3T2030 as it's functionally identical to P3T1035. >> V3 -> V4: >> - Add GENMASK for getting mask for conversion rates. >> - Add static arrays for containing sample times for different sensors. >> - Remove redundant code such as checking for NULL pointer in probe. >> - Improve readability by removing double negation. >> - Remove type cast where not required; make reg_buf & val_buf local. >> >> drivers/hwmon/Kconfig | 2 +- >> drivers/hwmon/tmp108.c | 203 +++++++++++++++++++++++++++++++++-------- >> 2 files changed, 164 insertions(+), 41 deletions(-) >> >> diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig >> index 157678b821fc..31969bddc812 100644 >> --- a/drivers/hwmon/Kconfig >> +++ b/drivers/hwmon/Kconfig >> @@ -2398,7 +2398,7 @@ config SENSORS_TMP108 >> select REGMAP_I3C if I3C >> help >> If you say yes here you get support for Texas Instruments TMP108 >> - sensor chips and NXP P3T1085. >> + sensor chips, NXP temperature sensors P3T1035, P3T1085 and P3T2030. >> >> This driver can also be built as a module. If so, the module >> will be called tmp108. >> diff --git a/drivers/hwmon/tmp108.c b/drivers/hwmon/tmp108.c >> index 60a237cbedbc..d308e2aed18a 100644 >> --- a/drivers/hwmon/tmp108.c >> +++ b/drivers/hwmon/tmp108.c >> @@ -17,9 +17,16 @@ >> #include <linux/regmap.h> >> #include <linux/regulator/consumer.h> >> #include <linux/slab.h> >> +#include <linux/util_macros.h> >> >> #define DRIVER_NAME "tmp108" >> >> +enum tmp108_hw_id { >> + P3T1035_ID, /* For sensors p3t1035 and p3t2030 */ >> + P3T1085_ID, >> + TMP108_ID, >> +}; >> + >> #define TMP108_REG_TEMP 0x00 >> #define TMP108_REG_CONF 0x01 >> #define TMP108_REG_TLOW 0x02 >> @@ -61,6 +68,7 @@ >> #define TMP108_CONVRATE_1HZ TMP108_CONF_CR0 /* Default */ >> #define TMP108_CONVRATE_4HZ TMP108_CONF_CR1 >> #define TMP108_CONVRATE_16HZ (TMP108_CONF_CR0|TMP108_CONF_CR1) >> +#define TMP108_CONVRATE_SHIFT 13 >> >> #define TMP108_CONF_HYSTERESIS_MASK (TMP108_CONF_HYS0|TMP108_CONF_HYS1) >> #define TMP108_HYSTERESIS_0C 0x0000 >> @@ -70,12 +78,23 @@ >> >> #define TMP108_CONVERSION_TIME_MS 30 /* in milli-seconds */ >> >> +#define TMP108_CONF_CR0_POS 13 >> +#define TMP108_CONF_CR1_POS 14 >> +#define TMP108_CONF_CONVRATE_FLD GENMASK(TMP108_CONF_CR1_POS, TMP108_CONF_CR0_POS) >> + >> struct tmp108 { >> - struct regmap *regmap; >> - u16 orig_config; >> - unsigned long ready_time; >> + struct regmap *regmap; >> + u16 orig_config; >> + unsigned long ready_time; > > don't mix format change in this patch. > Now prefer orignial format, just one space between type and field. > >> + enum tmp108_hw_id hw_id; >> + bool config_reg_16bits; >> + ushort *sample_times; >> + size_t n_sample_times; >> }; >> >> +ushort p3t1035_sample_times[] = {4000, 1000, 250, 125}; >> +ushort tmp108_sample_times[] = {4000, 1000, 250, 63}; >> + >> /* convert 12-bit TMP108 register value to milliCelsius */ >> static inline int tmp108_temp_reg_to_mC(s16 val) >> { >> @@ -101,21 +120,7 @@ static int tmp108_read(struct device *dev, enum hwmon_sensor_types type, >> ®val); >> if (err < 0) >> return err; >> - switch (regval & TMP108_CONF_CONVRATE_MASK) { >> - case TMP108_CONVRATE_0P25HZ: >> - default: >> - *temp = 4000; >> - break; >> - case TMP108_CONVRATE_1HZ: >> - *temp = 1000; >> - break; >> - case TMP108_CONVRATE_4HZ: >> - *temp = 250; >> - break; >> - case TMP108_CONVRATE_16HZ: >> - *temp = 63; >> - break; >> - } >> + *temp = tmp108->sample_times[FIELD_GET(TMP108_CONF_CONVRATE_FLD, regval)]; > > This code optimation need seperate patch. > No, There are now two ranges, not just one. >> return 0; >> } >> return -EOPNOTSUPP; >> @@ -192,22 +197,17 @@ static int tmp108_write(struct device *dev, enum hwmon_sensor_types type, >> { >> struct tmp108 *tmp108 = dev_get_drvdata(dev); >> u32 regval, mask; >> + u8 index; >> int err; >> >> if (type == hwmon_chip) { >> if (attr == hwmon_chip_update_interval) { >> - if (temp < 156) >> - mask = TMP108_CONVRATE_16HZ; >> - else if (temp < 625) >> - mask = TMP108_CONVRATE_4HZ; >> - else if (temp < 2500) >> - mask = TMP108_CONVRATE_1HZ; >> - else >> - mask = TMP108_CONVRATE_0P25HZ; >> + index = find_closest_descending(temp, tmp108->sample_times, >> + tmp108->n_sample_times); > > Need seperate patch for the code cleanup. > No. There are now two ranges, not just one. That is not a code cleanup, it is a change necessary to support multiple sets of ranges. Guenter >> return regmap_update_bits(tmp108->regmap, >> TMP108_REG_CONF, >> TMP108_CONF_CONVRATE_MASK, >> - mask); >> + FIELD_PREP(TMP108_CONF_CONVRATE_FLD, index)); >> } >> return -EOPNOTSUPP; >> } >> @@ -251,6 +251,8 @@ static int tmp108_write(struct device *dev, enum hwmon_sensor_types type, >> static umode_t tmp108_is_visible(const void *data, enum hwmon_sensor_types type, >> u32 attr, int channel) >> { >> + const struct tmp108 *tmp108 = data; >> + >> if (type == hwmon_chip && attr == hwmon_chip_update_interval) >> return 0644; >> >> @@ -264,8 +266,11 @@ static umode_t tmp108_is_visible(const void *data, enum hwmon_sensor_types type, >> return 0444; >> case hwmon_temp_min: >> case hwmon_temp_max: >> + return 0644; >> case hwmon_temp_min_hyst: >> case hwmon_temp_max_hyst: >> + if (tmp108->hw_id == P3T1035_ID) >> + return 0; >> return 0644; >> default: >> return 0; >> @@ -311,6 +316,106 @@ static bool tmp108_is_volatile_reg(struct device *dev, unsigned int reg) >> return reg == TMP108_REG_TEMP || reg == TMP108_REG_CONF; >> } >> >> +static int tmp108_i2c_reg_read(void *context, unsigned int reg, unsigned int *val) >> +{ >> + struct i2c_client *client = context; >> + struct tmp108 *tmp108 = i2c_get_clientdata(client); >> + int ret; >> + >> + if (reg == TMP108_REG_CONF && !tmp108->config_reg_16bits) { >> + ret = i2c_smbus_read_byte_data(client, TMP108_REG_CONF); >> + if (ret < 0) >> + return ret; >> + *val = ret << 8; >> + return 0; >> + } >> + >> + ret = i2c_smbus_read_word_swapped(client, reg); >> + if (ret < 0) >> + return ret; >> + *val = ret; >> + return 0; >> +} >> + >> +static int tmp108_i2c_reg_write(void *context, unsigned int reg, unsigned int val) >> +{ >> + struct i2c_client *client = context; >> + struct tmp108 *tmp108 = i2c_get_clientdata(client); >> + >> + if (reg == TMP108_REG_CONF && !tmp108->config_reg_16bits) >> + return i2c_smbus_write_byte_data(client, reg, val >> 8); >> + return i2c_smbus_write_word_swapped(client, reg, val); >> +} >> + >> +static const struct regmap_bus tmp108_i2c_regmap_bus = { >> + .reg_read = tmp108_i2c_reg_read, >> + .reg_write = tmp108_i2c_reg_write, >> +}; >> + >> +static int tmp108_i3c_reg_read(void *context, unsigned int reg, unsigned int *val) >> +{ >> + struct i3c_device *i3cdev = context; >> + struct tmp108 *tmp108 = i3cdev_get_drvdata(i3cdev); >> + u8 reg_buf[1], val_buf[2]; >> + struct i3c_xfer xfers[] = { >> + { >> + .rnw = false, >> + .len = 1, >> + .data.out = reg_buf, >> + }, >> + { >> + .rnw = true, >> + .len = 2, >> + .data.in = val_buf, >> + }, >> + }; >> + int ret; >> + >> + reg_buf[0] = reg; >> + >> + if (reg == TMP108_REG_CONF && !tmp108->config_reg_16bits) >> + xfers[1].len--; >> + >> + ret = i3c_device_do_xfers(i3cdev, xfers, 2, I3C_SDR); >> + if (ret < 0) >> + return ret; >> + >> + *val = val_buf[0] << 8; >> + if (reg != TMP108_REG_CONF || tmp108->config_reg_16bits) >> + *val |= val_buf[1]; >> + >> + return 0; >> +} >> + >> +static int tmp108_i3c_reg_write(void *context, unsigned int reg, unsigned int val) >> +{ >> + struct i3c_device *i3cdev = context; >> + struct tmp108 *tmp108 = i3cdev_get_drvdata(i3cdev); >> + u8 val_buf[3]; >> + struct i3c_xfer xfers[] = { >> + { >> + .rnw = false, >> + .len = 3, >> + .data.out = val_buf, >> + }, >> + }; >> + >> + val_buf[0] = reg; >> + val_buf[1] = (val >> 8) & 0xff; >> + >> + if (reg == TMP108_REG_CONF && !tmp108->config_reg_16bits) >> + xfers[0].len--; >> + else >> + val_buf[2] = val & 0xff; >> + >> + return i3c_device_do_xfers(i3cdev, xfers, 1, I3C_SDR); >> +} >> + >> +static const struct regmap_bus tmp108_i3c_regmap_bus = { >> + .reg_read = tmp108_i3c_reg_read, >> + .reg_write = tmp108_i3c_reg_write, >> +}; >> + >> static const struct regmap_config tmp108_regmap_config = { >> .reg_bits = 8, >> .val_bits = 16, >> @@ -323,7 +428,8 @@ static const struct regmap_config tmp108_regmap_config = { >> .use_single_write = true, >> }; >> >> -static int tmp108_common_probe(struct device *dev, struct regmap *regmap, char *name) >> +static int tmp108_common_probe(struct device *dev, struct regmap *regmap, char *name, >> + enum tmp108_hw_id hw_id) >> { >> struct device *hwmon_dev; >> struct tmp108 *tmp108; >> @@ -340,6 +446,15 @@ static int tmp108_common_probe(struct device *dev, struct regmap *regmap, char * >> >> dev_set_drvdata(dev, tmp108); >> tmp108->regmap = regmap; >> + tmp108->hw_id = hw_id; >> + tmp108->config_reg_16bits = (hw_id == P3T1035_ID) ? false : true; >> + if (hw_id == P3T1035_ID) { >> + tmp108->sample_times = p3t1035_sample_times; >> + tmp108->n_sample_times = ARRAY_SIZE(p3t1035_sample_times); >> + } else { >> + tmp108->sample_times = tmp108_sample_times; >> + tmp108->n_sample_times = ARRAY_SIZE(tmp108_sample_times); >> + } >> >> err = regmap_read(tmp108->regmap, TMP108_REG_CONF, &config); >> if (err < 0) { >> @@ -351,7 +466,6 @@ static int tmp108_common_probe(struct device *dev, struct regmap *regmap, char * >> /* Only continuous mode is supported. */ >> config &= ~TMP108_CONF_MODE_MASK; >> config |= TMP108_MODE_CONTINUOUS; >> - >> /* Only comparator mode is supported. */ >> config &= ~TMP108_CONF_TM; >> >> @@ -384,17 +498,20 @@ static int tmp108_probe(struct i2c_client *client) >> { >> struct device *dev = &client->dev; >> struct regmap *regmap; >> + enum tmp108_hw_id hw_id; >> >> if (!i2c_check_functionality(client->adapter, >> - I2C_FUNC_SMBUS_WORD_DATA)) >> + I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA)) >> return dev_err_probe(dev, -ENODEV, >> "adapter doesn't support SMBus word transactions\n"); >> >> - regmap = devm_regmap_init_i2c(client, &tmp108_regmap_config); >> + regmap = devm_regmap_init(dev, &tmp108_i2c_regmap_bus, client, &tmp108_regmap_config); >> if (IS_ERR(regmap)) >> return dev_err_probe(dev, PTR_ERR(regmap), "regmap init failed"); >> >> - return tmp108_common_probe(dev, regmap, client->name); >> + hw_id = (unsigned long)i2c_get_match_data(client); >> + >> + return tmp108_common_probe(dev, regmap, client->name, hw_id); >> } >> >> static int tmp108_suspend(struct device *dev) >> @@ -420,15 +537,17 @@ static int tmp108_resume(struct device *dev) >> static DEFINE_SIMPLE_DEV_PM_OPS(tmp108_dev_pm_ops, tmp108_suspend, tmp108_resume); >> >> static const struct i2c_device_id tmp108_i2c_ids[] = { >> - { "p3t1085" }, >> - { "tmp108" }, >> - { } >> + { "p3t1035", P3T1035_ID }, >> + { "p3t1085", P3T1085_ID }, >> + { "tmp108", TMP108_ID }, >> + {} >> }; >> MODULE_DEVICE_TABLE(i2c, tmp108_i2c_ids); >> >> static const struct of_device_id tmp108_of_ids[] = { >> - { .compatible = "nxp,p3t1085", }, >> - { .compatible = "ti,tmp108", }, >> + { .compatible = "nxp,p3t1035", .data = (void *)(uintptr_t)P3T1035_ID }, >> + { .compatible = "nxp,p3t1085", .data = (void *)(uintptr_t)P3T1085_ID }, >> + { .compatible = "ti,tmp108", .data = (void *)(uintptr_t)TMP108_ID }, > > Do not use device ID, define struct drvdata > > struct tmp108_drvdata > { > .samples = p3t1035_sample_times; > .reg_width = 16, > ... > } > > Frank >> {} >> }; >> MODULE_DEVICE_TABLE(of, tmp108_of_ids); >> @@ -444,7 +563,8 @@ static struct i2c_driver tmp108_driver = { >> }; >> >> static const struct i3c_device_id p3t1085_i3c_ids[] = { >> - I3C_DEVICE(0x011b, 0x1529, NULL), >> + I3C_DEVICE(0x011B, 0x1529, (void *)P3T1085_ID), >> + I3C_DEVICE(0x011B, 0x152B, (void *)P3T1035_ID), >> {} >> }; >> MODULE_DEVICE_TABLE(i3c, p3t1085_i3c_ids); >> @@ -453,13 +573,16 @@ static int p3t1085_i3c_probe(struct i3c_device *i3cdev) >> { >> struct device *dev = i3cdev_to_dev(i3cdev); >> struct regmap *regmap; >> + const struct i3c_device_id *id; >> >> - regmap = devm_regmap_init_i3c(i3cdev, &tmp108_regmap_config); >> + regmap = devm_regmap_init(dev, &tmp108_i3c_regmap_bus, 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"); >> + id = i3c_device_match_id(i3cdev, p3t1085_i3c_ids); >> + >> + return tmp108_common_probe(dev, regmap, "p3t1085_i3c", (unsigned long)id->data); >> } >> >> static struct i3c_driver p3t1085_driver = { >> -- >> 2.34.1 ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH v4 2/3] hwmon: (tmp108) Add support for P3T1035 and P3T2030 2026-01-17 0:36 ` Guenter Roeck @ 2026-01-18 17:30 ` Frank Li 2026-01-19 1:45 ` Guenter Roeck 0 siblings, 1 reply; 9+ messages in thread From: Frank Li @ 2026-01-18 17:30 UTC (permalink / raw) To: Guenter Roeck Cc: Mayank Mahajan, corbet, robh, krzk+dt, conor+dt, linux-hwmon, devicetree, linux-doc, linux-kernel, priyanka.jain, vikash.bansal On Fri, Jan 16, 2026 at 04:36:59PM -0800, Guenter Roeck wrote: > On 1/16/26 14:28, Frank Li wrote: > > On Fri, Jan 16, 2026 at 05:05:53PM +0530, Mayank Mahajan wrote: > > > Add support for the P3T1035 & P3T2030 temperature sensor. While mostly > > > compatible with the TMP108, P3T1035 uses an 8-bit configuration register > > > instead of the 16-bit layout used by TMP108. Updated driver to handle > > > this difference during configuration read/write. > > > > > > Signed-off-by: Mayank Mahajan <mayankmahajan.x@nxp.com> > > > --- > > > V1 -> V2: > > > - Disabled hysteresis in is_visible function for P3T1035. > > > - Added tables for conversion rate similar to the LM75 driver. > > > - Implemented different bus access depending on the chip being used. > > > - Removed regmap for 8 bits; now we are using one regmap as before. > > > - Added read and write functions for i2c and i3c for use with regmap. > > > - Mapped the 8-bit configuration register to a 16 bit value for P3T1035. > > > V2 -> V3: > > > - Remove changes not relevant to adding a new device in the driver. > > > - Address warnings due to incorrect usage of casting operations. > > > - Remove the usage of P3T2030 as it's functionally identical to P3T1035. > > > V3 -> V4: > > > - Add GENMASK for getting mask for conversion rates. > > > - Add static arrays for containing sample times for different sensors. > > > - Remove redundant code such as checking for NULL pointer in probe. > > > - Improve readability by removing double negation. > > > - Remove type cast where not required; make reg_buf & val_buf local. > > > > > > drivers/hwmon/Kconfig | 2 +- > > > drivers/hwmon/tmp108.c | 203 +++++++++++++++++++++++++++++++++-------- > > > 2 files changed, 164 insertions(+), 41 deletions(-) > > > > > > diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig > > > index 157678b821fc..31969bddc812 100644 > > > --- a/drivers/hwmon/Kconfig > > > +++ b/drivers/hwmon/Kconfig > > > @@ -2398,7 +2398,7 @@ config SENSORS_TMP108 > > > select REGMAP_I3C if I3C > > > help > > > If you say yes here you get support for Texas Instruments TMP108 > > > - sensor chips and NXP P3T1085. > > > + sensor chips, NXP temperature sensors P3T1035, P3T1085 and P3T2030. > > > > > > This driver can also be built as a module. If so, the module > > > will be called tmp108. > > > diff --git a/drivers/hwmon/tmp108.c b/drivers/hwmon/tmp108.c > > > index 60a237cbedbc..d308e2aed18a 100644 > > > --- a/drivers/hwmon/tmp108.c > > > +++ b/drivers/hwmon/tmp108.c > > > @@ -17,9 +17,16 @@ > > > #include <linux/regmap.h> > > > #include <linux/regulator/consumer.h> > > > #include <linux/slab.h> > > > +#include <linux/util_macros.h> > > > > > > #define DRIVER_NAME "tmp108" > > > > > > +enum tmp108_hw_id { > > > + P3T1035_ID, /* For sensors p3t1035 and p3t2030 */ > > > + P3T1085_ID, > > > + TMP108_ID, > > > +}; > > > + > > > #define TMP108_REG_TEMP 0x00 > > > #define TMP108_REG_CONF 0x01 > > > #define TMP108_REG_TLOW 0x02 > > > @@ -61,6 +68,7 @@ > > > #define TMP108_CONVRATE_1HZ TMP108_CONF_CR0 /* Default */ > > > #define TMP108_CONVRATE_4HZ TMP108_CONF_CR1 > > > #define TMP108_CONVRATE_16HZ (TMP108_CONF_CR0|TMP108_CONF_CR1) > > > +#define TMP108_CONVRATE_SHIFT 13 > > > > > > #define TMP108_CONF_HYSTERESIS_MASK (TMP108_CONF_HYS0|TMP108_CONF_HYS1) > > > #define TMP108_HYSTERESIS_0C 0x0000 > > > @@ -70,12 +78,23 @@ > > > > > > #define TMP108_CONVERSION_TIME_MS 30 /* in milli-seconds */ > > > > > > +#define TMP108_CONF_CR0_POS 13 > > > +#define TMP108_CONF_CR1_POS 14 > > > +#define TMP108_CONF_CONVRATE_FLD GENMASK(TMP108_CONF_CR1_POS, TMP108_CONF_CR0_POS) > > > + > > > struct tmp108 { > > > - struct regmap *regmap; > > > - u16 orig_config; > > > - unsigned long ready_time; > > > + struct regmap *regmap; > > > + u16 orig_config; > > > + unsigned long ready_time; > > > > don't mix format change in this patch. > > Now prefer orignial format, just one space between type and field. > > > > > + enum tmp108_hw_id hw_id; > > > + bool config_reg_16bits; > > > + ushort *sample_times; > > > + size_t n_sample_times; > > > }; > > > > > > +ushort p3t1035_sample_times[] = {4000, 1000, 250, 125}; > > > +ushort tmp108_sample_times[] = {4000, 1000, 250, 63}; > > > + > > > /* convert 12-bit TMP108 register value to milliCelsius */ > > > static inline int tmp108_temp_reg_to_mC(s16 val) > > > { > > > @@ -101,21 +120,7 @@ static int tmp108_read(struct device *dev, enum hwmon_sensor_types type, > > > ®val); > > > if (err < 0) > > > return err; > > > - switch (regval & TMP108_CONF_CONVRATE_MASK) { > > > - case TMP108_CONVRATE_0P25HZ: > > > - default: > > > - *temp = 4000; > > > - break; > > > - case TMP108_CONVRATE_1HZ: > > > - *temp = 1000; > > > - break; > > > - case TMP108_CONVRATE_4HZ: > > > - *temp = 250; > > > - break; > > > - case TMP108_CONVRATE_16HZ: > > > - *temp = 63; > > > - break; > > > - } > > > + *temp = tmp108->sample_times[FIELD_GET(TMP108_CONF_CONVRATE_FLD, regval)]; > > > > This code optimation need seperate patch. > > > No, There are now two ranges, not just one. Previous code use swtich case to handle sample. now convert to use a map array tmp108_sample_times[]. My means use a small patch convert existed switch case to map array firstly , then add second range, which make code easy to review. > > > > return 0; > > > } > > > return -EOPNOTSUPP; > > > @@ -192,22 +197,17 @@ static int tmp108_write(struct device *dev, enum hwmon_sensor_types type, > > > { > > > struct tmp108 *tmp108 = dev_get_drvdata(dev); > > > u32 regval, mask; > > > + u8 index; > > > int err; > > > > > > if (type == hwmon_chip) { > > > if (attr == hwmon_chip_update_interval) { > > > - if (temp < 156) > > > - mask = TMP108_CONVRATE_16HZ; > > > - else if (temp < 625) > > > - mask = TMP108_CONVRATE_4HZ; > > > - else if (temp < 2500) > > > - mask = TMP108_CONVRATE_1HZ; > > > - else > > > - mask = TMP108_CONVRATE_0P25HZ; > > > + index = find_closest_descending(temp, tmp108->sample_times, > > > + tmp108->n_sample_times); > > > > Need seperate patch for the code cleanup. > > > > No. There are now two ranges, not just one. That is not a code cleanup, > it is a change necessary to support multiple sets of ranges. The smae here, this code just convert if else to helper function find_closest_descending(), which is not related work, which add new part support. Frank > > Guenter > > > > return regmap_update_bits(tmp108->regmap, > > > TMP108_REG_CONF, > > > TMP108_CONF_CONVRATE_MASK, > > > - mask); > > > + FIELD_PREP(TMP108_CONF_CONVRATE_FLD, index)); > > > } > > > return -EOPNOTSUPP; > > > } > > > @@ -251,6 +251,8 @@ static int tmp108_write(struct device *dev, enum hwmon_sensor_types type, > > > static umode_t tmp108_is_visible(const void *data, enum hwmon_sensor_types type, > > > u32 attr, int channel) > > > { > > > + const struct tmp108 *tmp108 = data; > > > + > > > if (type == hwmon_chip && attr == hwmon_chip_update_interval) > > > return 0644; > > > > > > @@ -264,8 +266,11 @@ static umode_t tmp108_is_visible(const void *data, enum hwmon_sensor_types type, > > > return 0444; > > > case hwmon_temp_min: > > > case hwmon_temp_max: > > > + return 0644; > > > case hwmon_temp_min_hyst: > > > case hwmon_temp_max_hyst: > > > + if (tmp108->hw_id == P3T1035_ID) > > > + return 0; > > > return 0644; > > > default: > > > return 0; > > > @@ -311,6 +316,106 @@ static bool tmp108_is_volatile_reg(struct device *dev, unsigned int reg) > > > return reg == TMP108_REG_TEMP || reg == TMP108_REG_CONF; > > > } > > > > > > +static int tmp108_i2c_reg_read(void *context, unsigned int reg, unsigned int *val) > > > +{ > > > + struct i2c_client *client = context; > > > + struct tmp108 *tmp108 = i2c_get_clientdata(client); > > > + int ret; > > > + > > > + if (reg == TMP108_REG_CONF && !tmp108->config_reg_16bits) { > > > + ret = i2c_smbus_read_byte_data(client, TMP108_REG_CONF); > > > + if (ret < 0) > > > + return ret; > > > + *val = ret << 8; > > > + return 0; > > > + } > > > + > > > + ret = i2c_smbus_read_word_swapped(client, reg); > > > + if (ret < 0) > > > + return ret; > > > + *val = ret; > > > + return 0; > > > +} > > > + > > > +static int tmp108_i2c_reg_write(void *context, unsigned int reg, unsigned int val) > > > +{ > > > + struct i2c_client *client = context; > > > + struct tmp108 *tmp108 = i2c_get_clientdata(client); > > > + > > > + if (reg == TMP108_REG_CONF && !tmp108->config_reg_16bits) > > > + return i2c_smbus_write_byte_data(client, reg, val >> 8); > > > + return i2c_smbus_write_word_swapped(client, reg, val); > > > +} > > > + > > > +static const struct regmap_bus tmp108_i2c_regmap_bus = { > > > + .reg_read = tmp108_i2c_reg_read, > > > + .reg_write = tmp108_i2c_reg_write, > > > +}; > > > + > > > +static int tmp108_i3c_reg_read(void *context, unsigned int reg, unsigned int *val) > > > +{ > > > + struct i3c_device *i3cdev = context; > > > + struct tmp108 *tmp108 = i3cdev_get_drvdata(i3cdev); > > > + u8 reg_buf[1], val_buf[2]; > > > + struct i3c_xfer xfers[] = { > > > + { > > > + .rnw = false, > > > + .len = 1, > > > + .data.out = reg_buf, > > > + }, > > > + { > > > + .rnw = true, > > > + .len = 2, > > > + .data.in = val_buf, > > > + }, > > > + }; > > > + int ret; > > > + > > > + reg_buf[0] = reg; > > > + > > > + if (reg == TMP108_REG_CONF && !tmp108->config_reg_16bits) > > > + xfers[1].len--; > > > + > > > + ret = i3c_device_do_xfers(i3cdev, xfers, 2, I3C_SDR); > > > + if (ret < 0) > > > + return ret; > > > + > > > + *val = val_buf[0] << 8; > > > + if (reg != TMP108_REG_CONF || tmp108->config_reg_16bits) > > > + *val |= val_buf[1]; > > > + > > > + return 0; > > > +} > > > + > > > +static int tmp108_i3c_reg_write(void *context, unsigned int reg, unsigned int val) > > > +{ > > > + struct i3c_device *i3cdev = context; > > > + struct tmp108 *tmp108 = i3cdev_get_drvdata(i3cdev); > > > + u8 val_buf[3]; > > > + struct i3c_xfer xfers[] = { > > > + { > > > + .rnw = false, > > > + .len = 3, > > > + .data.out = val_buf, > > > + }, > > > + }; > > > + > > > + val_buf[0] = reg; > > > + val_buf[1] = (val >> 8) & 0xff; > > > + > > > + if (reg == TMP108_REG_CONF && !tmp108->config_reg_16bits) > > > + xfers[0].len--; > > > + else > > > + val_buf[2] = val & 0xff; > > > + > > > + return i3c_device_do_xfers(i3cdev, xfers, 1, I3C_SDR); > > > +} > > > + > > > +static const struct regmap_bus tmp108_i3c_regmap_bus = { > > > + .reg_read = tmp108_i3c_reg_read, > > > + .reg_write = tmp108_i3c_reg_write, > > > +}; > > > + > > > static const struct regmap_config tmp108_regmap_config = { > > > .reg_bits = 8, > > > .val_bits = 16, > > > @@ -323,7 +428,8 @@ static const struct regmap_config tmp108_regmap_config = { > > > .use_single_write = true, > > > }; > > > > > > -static int tmp108_common_probe(struct device *dev, struct regmap *regmap, char *name) > > > +static int tmp108_common_probe(struct device *dev, struct regmap *regmap, char *name, > > > + enum tmp108_hw_id hw_id) > > > { > > > struct device *hwmon_dev; > > > struct tmp108 *tmp108; > > > @@ -340,6 +446,15 @@ static int tmp108_common_probe(struct device *dev, struct regmap *regmap, char * > > > > > > dev_set_drvdata(dev, tmp108); > > > tmp108->regmap = regmap; > > > + tmp108->hw_id = hw_id; > > > + tmp108->config_reg_16bits = (hw_id == P3T1035_ID) ? false : true; > > > + if (hw_id == P3T1035_ID) { > > > + tmp108->sample_times = p3t1035_sample_times; > > > + tmp108->n_sample_times = ARRAY_SIZE(p3t1035_sample_times); > > > + } else { > > > + tmp108->sample_times = tmp108_sample_times; > > > + tmp108->n_sample_times = ARRAY_SIZE(tmp108_sample_times); > > > + } > > > > > > err = regmap_read(tmp108->regmap, TMP108_REG_CONF, &config); > > > if (err < 0) { > > > @@ -351,7 +466,6 @@ static int tmp108_common_probe(struct device *dev, struct regmap *regmap, char * > > > /* Only continuous mode is supported. */ > > > config &= ~TMP108_CONF_MODE_MASK; > > > config |= TMP108_MODE_CONTINUOUS; > > > - > > > /* Only comparator mode is supported. */ > > > config &= ~TMP108_CONF_TM; > > > > > > @@ -384,17 +498,20 @@ static int tmp108_probe(struct i2c_client *client) > > > { > > > struct device *dev = &client->dev; > > > struct regmap *regmap; > > > + enum tmp108_hw_id hw_id; > > > > > > if (!i2c_check_functionality(client->adapter, > > > - I2C_FUNC_SMBUS_WORD_DATA)) > > > + I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA)) > > > return dev_err_probe(dev, -ENODEV, > > > "adapter doesn't support SMBus word transactions\n"); > > > > > > - regmap = devm_regmap_init_i2c(client, &tmp108_regmap_config); > > > + regmap = devm_regmap_init(dev, &tmp108_i2c_regmap_bus, client, &tmp108_regmap_config); > > > if (IS_ERR(regmap)) > > > return dev_err_probe(dev, PTR_ERR(regmap), "regmap init failed"); > > > > > > - return tmp108_common_probe(dev, regmap, client->name); > > > + hw_id = (unsigned long)i2c_get_match_data(client); > > > + > > > + return tmp108_common_probe(dev, regmap, client->name, hw_id); > > > } > > > > > > static int tmp108_suspend(struct device *dev) > > > @@ -420,15 +537,17 @@ static int tmp108_resume(struct device *dev) > > > static DEFINE_SIMPLE_DEV_PM_OPS(tmp108_dev_pm_ops, tmp108_suspend, tmp108_resume); > > > > > > static const struct i2c_device_id tmp108_i2c_ids[] = { > > > - { "p3t1085" }, > > > - { "tmp108" }, > > > - { } > > > + { "p3t1035", P3T1035_ID }, > > > + { "p3t1085", P3T1085_ID }, > > > + { "tmp108", TMP108_ID }, > > > + {} > > > }; > > > MODULE_DEVICE_TABLE(i2c, tmp108_i2c_ids); > > > > > > static const struct of_device_id tmp108_of_ids[] = { > > > - { .compatible = "nxp,p3t1085", }, > > > - { .compatible = "ti,tmp108", }, > > > + { .compatible = "nxp,p3t1035", .data = (void *)(uintptr_t)P3T1035_ID }, > > > + { .compatible = "nxp,p3t1085", .data = (void *)(uintptr_t)P3T1085_ID }, > > > + { .compatible = "ti,tmp108", .data = (void *)(uintptr_t)TMP108_ID }, > > > > Do not use device ID, define struct drvdata > > > > struct tmp108_drvdata > > { > > .samples = p3t1035_sample_times; > > .reg_width = 16, > > ... > > } > > > > Frank > > > {} > > > }; > > > MODULE_DEVICE_TABLE(of, tmp108_of_ids); > > > @@ -444,7 +563,8 @@ static struct i2c_driver tmp108_driver = { > > > }; > > > > > > static const struct i3c_device_id p3t1085_i3c_ids[] = { > > > - I3C_DEVICE(0x011b, 0x1529, NULL), > > > + I3C_DEVICE(0x011B, 0x1529, (void *)P3T1085_ID), > > > + I3C_DEVICE(0x011B, 0x152B, (void *)P3T1035_ID), > > > {} > > > }; > > > MODULE_DEVICE_TABLE(i3c, p3t1085_i3c_ids); > > > @@ -453,13 +573,16 @@ static int p3t1085_i3c_probe(struct i3c_device *i3cdev) > > > { > > > struct device *dev = i3cdev_to_dev(i3cdev); > > > struct regmap *regmap; > > > + const struct i3c_device_id *id; > > > > > > - regmap = devm_regmap_init_i3c(i3cdev, &tmp108_regmap_config); > > > + regmap = devm_regmap_init(dev, &tmp108_i3c_regmap_bus, 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"); > > > + id = i3c_device_match_id(i3cdev, p3t1085_i3c_ids); > > > + > > > + return tmp108_common_probe(dev, regmap, "p3t1085_i3c", (unsigned long)id->data); > > > } > > > > > > static struct i3c_driver p3t1085_driver = { > > > -- > > > 2.34.1 > ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH v4 2/3] hwmon: (tmp108) Add support for P3T1035 and P3T2030 2026-01-18 17:30 ` Frank Li @ 2026-01-19 1:45 ` Guenter Roeck 0 siblings, 0 replies; 9+ messages in thread From: Guenter Roeck @ 2026-01-19 1:45 UTC (permalink / raw) To: Frank Li Cc: Mayank Mahajan, corbet, robh, krzk+dt, conor+dt, linux-hwmon, devicetree, linux-doc, linux-kernel, priyanka.jain, vikash.bansal Frank, On 1/18/26 09:30, Frank Li wrote: ... >>>> @@ -101,21 +120,7 @@ static int tmp108_read(struct device *dev, enum hwmon_sensor_types type, >>>> ®val); >>>> if (err < 0) >>>> return err; >>>> - switch (regval & TMP108_CONF_CONVRATE_MASK) { >>>> - case TMP108_CONVRATE_0P25HZ: >>>> - default: >>>> - *temp = 4000; >>>> - break; >>>> - case TMP108_CONVRATE_1HZ: >>>> - *temp = 1000; >>>> - break; >>>> - case TMP108_CONVRATE_4HZ: >>>> - *temp = 250; >>>> - break; >>>> - case TMP108_CONVRATE_16HZ: >>>> - *temp = 63; >>>> - break; >>>> - } >>>> + *temp = tmp108->sample_times[FIELD_GET(TMP108_CONF_CONVRATE_FLD, regval)]; >>> >>> This code optimation need seperate patch. >>> >> No, There are now two ranges, not just one. > > Previous code use swtich case to handle sample. now convert to use a map > array tmp108_sample_times[]. > > My means use a small patch convert existed switch case to map array firstly > , then add second range, which make code easy to review. > You are not signed up as reviewer of this driver. I am, and I don't want to see a separate patch just for this because it means extra work for me. Thanks, Guenter ^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH v4 3/3] hwmon: (tmp108) Add P3T1035 and P3T2030 support 2026-01-16 11:35 [PATCH v4 1/3] dt-bindings: hwmon: ti,tmp108: Add P3T1035,P3T2030 Mayank Mahajan 2026-01-16 11:35 ` [PATCH v4 2/3] hwmon: (tmp108) Add support for P3T1035 and P3T2030 Mayank Mahajan @ 2026-01-16 11:35 ` Mayank Mahajan 2026-01-16 14:38 ` [PATCH v4 1/3] dt-bindings: hwmon: ti,tmp108: Add P3T1035,P3T2030 Krzysztof Kozlowski 2 siblings, 0 replies; 9+ messages in thread From: Mayank Mahajan @ 2026-01-16 11:35 UTC (permalink / raw) To: linux, corbet, robh, krzk+dt, conor+dt, linux-hwmon, devicetree, linux-doc, linux-kernel Cc: priyanka.jain, vikash.bansal, Mayank Mahajan Update the hwmon driver documentation for sensors: P3T1035 and P3T2030. Signed-off-by: Mayank Mahajan <mayankmahajan.x@nxp.com> --- V1 -> V2: - No changes in v2. V2 -> V3: - No changes in v3. V3 -> V4: - No changes in v4. Documentation/hwmon/tmp108.rst | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/Documentation/hwmon/tmp108.rst b/Documentation/hwmon/tmp108.rst index bc4941d98268..c218ea333dd6 100644 --- a/Documentation/hwmon/tmp108.rst +++ b/Documentation/hwmon/tmp108.rst @@ -3,6 +3,15 @@ Kernel driver tmp108 Supported chips: + * NXP P3T1035 + + Prefix: 'p3t1035' + + Addresses scanned: none + + Datasheet: https://www.nxp.com/docs/en/data-sheet/P3T1035XUK_P3T2030XUK.pdf + + * NXP P3T1085 Prefix: 'p3t1085' @@ -11,6 +20,14 @@ Supported chips: Datasheet: https://www.nxp.com/docs/en/data-sheet/P3T1085UK.pdf + * NXP P3T2030 + + Prefix: 'p3t2030' + + Addresses scanned: none + + Datasheet: https://www.nxp.com/docs/en/data-sheet/P3T1035XUK_P3T2030XUK.pdf + * Texas Instruments TMP108 Prefix: 'tmp108' -- 2.34.1 ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH v4 1/3] dt-bindings: hwmon: ti,tmp108: Add P3T1035,P3T2030 2026-01-16 11:35 [PATCH v4 1/3] dt-bindings: hwmon: ti,tmp108: Add P3T1035,P3T2030 Mayank Mahajan 2026-01-16 11:35 ` [PATCH v4 2/3] hwmon: (tmp108) Add support for P3T1035 and P3T2030 Mayank Mahajan 2026-01-16 11:35 ` [PATCH v4 3/3] hwmon: (tmp108) Add P3T1035 and P3T2030 support Mayank Mahajan @ 2026-01-16 14:38 ` Krzysztof Kozlowski 2 siblings, 0 replies; 9+ messages in thread From: Krzysztof Kozlowski @ 2026-01-16 14:38 UTC (permalink / raw) To: Mayank Mahajan, linux, corbet, robh, krzk+dt, conor+dt, linux-hwmon, devicetree, linux-doc, linux-kernel Cc: priyanka.jain, vikash.bansal On 16/01/2026 12:35, Mayank Mahajan wrote: > Document the NXP P3T1035 and P3T2030 compatibles in TMP108. > > Signed-off-by: Mayank Mahajan <mayankmahajan.x@nxp.com> Read carefully replies you receive. <form letter> This is a friendly reminder during the review process. It looks like you received a tag and forgot to add it. If you do not know the process, here is a short explanation: Please add Acked-by/Reviewed-by/Tested-by tags when posting new versions of patchset, under or above your Signed-off-by tag, unless patch changed significantly (e.g. new properties added to the DT bindings). Tag is "received", when provided in a message replied to you on the mailing list. Tools like b4 can help here. However, there's no need to repost patches *only* to add the tags. The upstream maintainer will do that for tags received on the version they apply. Please read: https://elixir.bootlin.com/linux/v6.12-rc3/source/Documentation/process/submitting-patches.rst#L577 If a tag was not added on purpose, please state why and what changed. </form letter> Best regards, Krzysztof ^ permalink raw reply [flat|nested] 9+ messages in thread
end of thread, other threads:[~2026-01-19 1:45 UTC | newest] Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2026-01-16 11:35 [PATCH v4 1/3] dt-bindings: hwmon: ti,tmp108: Add P3T1035,P3T2030 Mayank Mahajan 2026-01-16 11:35 ` [PATCH v4 2/3] hwmon: (tmp108) Add support for P3T1035 and P3T2030 Mayank Mahajan 2026-01-16 21:37 ` kernel test robot 2026-01-16 22:28 ` Frank Li 2026-01-17 0:36 ` Guenter Roeck 2026-01-18 17:30 ` Frank Li 2026-01-19 1:45 ` Guenter Roeck 2026-01-16 11:35 ` [PATCH v4 3/3] hwmon: (tmp108) Add P3T1035 and P3T2030 support Mayank Mahajan 2026-01-16 14:38 ` [PATCH v4 1/3] dt-bindings: hwmon: ti,tmp108: Add P3T1035,P3T2030 Krzysztof Kozlowski
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®