From nobody Wed Apr 1 08:16:42 2026 Received: from mail-wr1-f42.google.com (mail-wr1-f42.google.com [209.85.221.42]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 8A3C343CEED for ; Tue, 31 Mar 2026 17:55:00 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.221.42 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774979705; cv=none; b=t8WSPdWCyBkFmX/1JqiVjAiIMUJhDGAHxoQCjptqu9PFdl4r/EzeAxJnkf7v5VdauGU3YxfsP5e7wl31N5ey8cViPlEsR2S31+QsNlLCm79NS2wHL38MwA8N0DIJw+w6Im+WvS3yE1bQj7B+/5EQaBsKrx0tSSzRAWaJR1tadTs= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774979705; c=relaxed/simple; bh=1jp1OboeQ+O1ET4HZOtv99KLrYPGTbApOMJgCl0hKWs=; h=From:To:Cc:Subject:Date:Message-ID:MIME-Version; b=rQHvRxawOUz0SF6XRYqApW7eeAZZoBeZk/y2rbdCy7yQbE4OnQ8ee+C4TrUJiyfywiUS9TEe/7km7Md3xsuSIghjqdiqXZn4Ey0lN+T6KpT5Z2I2JJonI91RVcigGAoTVnynPYTyBBwCpk9bz3W2o5ZgFPFDXJJo2qqGPTzfeJ4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=mJQcmWxh; arc=none smtp.client-ip=209.85.221.42 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="mJQcmWxh" Received: by mail-wr1-f42.google.com with SMTP id ffacd0b85a97d-43ccda008cdso100553f8f.0 for ; Tue, 31 Mar 2026 10:55:00 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1774979698; x=1775584498; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:from:to:cc:subject:date:message-id:reply-to; bh=JFoqX0s456APxRZScJ0cr+kcv9K0kU4851+kyMBYLdI=; b=mJQcmWxhGjTqmnEdaRcKiQ/uamzaglkZssONzpkzqp+d9Yun7H9rEJ5HoZHQyPtBif 6bp5TH6jI9YtqK9IrBrEWPlwm0SfLJRRn1TUGrnNp4q2OhjW9OGxON6UYTL+4aIfOYU9 wTIG9CODyZpGU3Ev3Zp27JJR4y9bzNXZbSbOzJ5zfRVlI5zVlEdSPnyG2lZrV6+8Kh5/ i+Z/Qv6d1LOrorCp5aMuxnLpEqgIkxXWvQSn9onJtROU4O9nRlD8XlVuLH/AFlWvYhRO e490NWkMlygazQkUj/J9j/BrwFAx69Mo3cnE5vJkbayD0/yGn14c24I/WDff1kOC8JoV NaWA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1774979698; x=1775584498; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:x-gm-gg:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to; bh=JFoqX0s456APxRZScJ0cr+kcv9K0kU4851+kyMBYLdI=; b=f8cueDo3rJczm82woknFOgQ2cJe/6gOpk8bbzGLFf+C097Rf1PhqRSoZD70u55kPaF scab+9635Ll56rs2+TN1S93/EvH/IzBrFgDgY4l30I8PG2EOLDfMKSvkzjEkTNnwmK9l +BG/CqY35/K5LWfnBbWf9RZzuivtbU2eIQUa/znZSi9vT3kAUrKVTJnF82M6zMZFUjyx 8nQ6Cp4kP0HCukAg8PXGmriE0BZUp377OyiiV73vWzBQlDGCbUNN0YEII6A4gdHJkfqY z2XLYxyMAvC+7ZjUvNFPPn6mClbA42pdOelTv6xx/CnofSG89hdWcDgzbp/Dy6G40cp9 ISXA== X-Forwarded-Encrypted: i=1; AJvYcCVY/ZteMbzemdjmvH+w6iAUMrzl8lQTw4aRovp0h0QjQu9c5gmWoDj7F8/cSne9LoVnqo6M+Jo2O/cu5g4=@vger.kernel.org X-Gm-Message-State: AOJu0Yy9WXhNdQX1pXUxC4y/CiiwwZZoiDCBMjVYXpLFnEdyin59XR4w m0kHZytEtHSw96pVAUDXZv8U7O//YYKcUq4A7eVF1PJ7C5O4NDgsd3wY X-Gm-Gg: ATEYQzzXNNKbMmQAjdppy5NZCvnyn6iZ1I1f881y118vKSOsh/fLT1X/kxHjBDbGYxy Wi4cc3QsDQuOubpYwAo3ORrF5PCgGNy7kcaOKutsmCRyZ8h/Euc1araZ8X8KTeQotQz9xkctjop DDxhP3NtyNRFpHAZj7hkQlUk0yaNBaRE25W+5LDF+LRAfMCOlmlq2eZt5xL/+rT4wkk0F3nljU+ /NoOd1h/ra5MEkfjduTb/deANcfQN5myt3E075AHSN4jPQfTHJl/i821qKdqYhQi7CDz4ovrfui smTY5L5NX9eAJSsMLkyugm8LD6eJH3mZaItOskJsci0ppWXfdJvB/N5BCUJDHENXDxxODHgxBUe sgc5R/sMfxLrzCy7qcxf8OdNrGknuzEPlTOnfbA5lxaOurNUzjAgHSR0cDZwi6Qlqb67OJ4C5c2 3FeqEdnKiP7TsbX+MUjshS56qQyLMo1l9DASkzyIjd9ae0h6tCw1so1gleq131qj6SXMrBuCty5 Q== X-Received: by 2002:adf:fa52:0:b0:43d:1598:2d6e with SMTP id ffacd0b85a97d-43d15982eb7mr217393f8f.20.1774979697518; Tue, 31 Mar 2026 10:54:57 -0700 (PDT) Received: from flaviu-Aspire-E5-572G.. ([93.122.249.8]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-43cf245e2f6sm29901913f8f.18.2026.03.31.10.54.56 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 31 Mar 2026 10:54:56 -0700 (PDT) From: Flaviu Nistor To: Guenter Roeck , Jonathan Corbet , Shuah Khan Cc: Flaviu Nistor , linux-hwmon@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH] hwmon:tmp102: add support for update interval Date: Tue, 31 Mar 2026 20:54:18 +0300 Message-ID: <20260331175418.16145-1-flaviu.nistor@gmail.com> X-Mailer: git-send-email 2.43.0 Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Since the sensor supports different sampling intervals via bits CR0 and CR1 from the CONFIG register, add support in order for the conversion rate to be changed from user space. Default is 4 conv/sec. Signed-off-by: Flaviu Nistor --- Documentation/hwmon/tmp102.rst | 19 +++- drivers/hwmon/tmp102.c | 165 ++++++++++++++++++++++++--------- 2 files changed, 139 insertions(+), 45 deletions(-) diff --git a/Documentation/hwmon/tmp102.rst b/Documentation/hwmon/tmp102.rst index 3c2cb5bab1e9..7ed649ac4cd0 100644 --- a/Documentation/hwmon/tmp102.rst +++ b/Documentation/hwmon/tmp102.rst @@ -41,12 +41,25 @@ degree from -40 to +125 C. Resolution of the sensor is = 0.0625 degree. The operating temperature has a minimum of -55 C and a maximum of +150 C. =20 The TMP102 has a programmable update rate that can select between 8, 4, 1,= and -0.5 Hz. (Currently the driver only supports the default of 4 Hz). +0.5 Hz. =20 The TMP110 and TMP113 are software compatible with TMP102, but have differ= ent accuracy (maximum error) specifications. The TMP110 has an accuracy (maxim= um error) of 1.0 degree, TMP113 has an accuracy (maximum error) of 0.3 degree, while= TMP102 has an accuracy (maximum error) of 2.0 degree. =20 -The driver provides the common sysfs-interface for temperatures (see -Documentation/hwmon/sysfs-interface.rst under Temperatures). +sysfs-Interface +--------------- + +The following list includes the sysfs attributes that the driver provides,= their +permissions and a short description: + +=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D =3D=3D=3D=3D=3D=3D=3D =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D +Name Perm Description +=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D =3D=3D=3D=3D=3D=3D=3D =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D +temp1_input: RO Temperature input +temp1_label: RO Descriptive name for the sensor +temp1_max: RW Maximum temperature +temp1_max_hyst: RW Maximum hysteresis temperature +update_interval RW Update conversions interval in mil= liseconds +=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D =3D=3D=3D=3D=3D=3D=3D =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D diff --git a/drivers/hwmon/tmp102.c b/drivers/hwmon/tmp102.c index 5b10c395a84d..c0805f6271b9 100644 --- a/drivers/hwmon/tmp102.c +++ b/drivers/hwmon/tmp102.c @@ -50,11 +50,25 @@ =20 #define CONVERSION_TIME_MS 35 /* in milli-seconds */ =20 +struct tmp102_params { + u16 default_sample_time; + u8 num_sample_times; + const unsigned int *sample_times; +}; + struct tmp102 { const char *label; struct regmap *regmap; u16 config_orig; unsigned long ready_time; + u16 sample_time; + const struct tmp102_params *params; +}; + +static const struct tmp102_params device_params =3D { + .default_sample_time =3D 125, + .num_sample_times =3D 4, + .sample_times =3D (unsigned int []){ 125, 250, 1000, 4000 }, }; =20 /* convert left adjusted 13-bit TMP102 register value to milliCelsius */ @@ -80,58 +94,113 @@ static int tmp102_read_string(struct device *dev, enum= hwmon_sensor_types type, } =20 static int tmp102_read(struct device *dev, enum hwmon_sensor_types type, - u32 attr, int channel, long *temp) + u32 attr, int channel, long *val) { struct tmp102 *tmp102 =3D dev_get_drvdata(dev); unsigned int regval; int err, reg; =20 - switch (attr) { - case hwmon_temp_input: - /* Is it too early to return a conversion ? */ - if (time_before(jiffies, tmp102->ready_time)) { - dev_dbg(dev, "%s: Conversion not ready yet..\n", __func__); - return -EAGAIN; + switch (type) { + case hwmon_chip: + switch (attr) { + case hwmon_chip_update_interval: + *val =3D tmp102->sample_time; + break; + default: + return -EINVAL; } - reg =3D TMP102_TEMP_REG; break; - case hwmon_temp_max_hyst: - reg =3D TMP102_TLOW_REG; - break; - case hwmon_temp_max: - reg =3D TMP102_THIGH_REG; + case hwmon_temp: + switch (attr) { + case hwmon_temp_input: + /* Is it too early to return a conversion ? */ + if (time_before(jiffies, tmp102->ready_time)) { + dev_dbg(dev, "%s: Conversion not ready yet..\n", __func__); + return -EAGAIN; + } + reg =3D TMP102_TEMP_REG; + break; + case hwmon_temp_max_hyst: + reg =3D TMP102_TLOW_REG; + break; + case hwmon_temp_max: + reg =3D TMP102_THIGH_REG; + break; + default: + return -EOPNOTSUPP; + } + err =3D regmap_read(tmp102->regmap, reg, ®val); + if (err < 0) + return err; + *val =3D tmp102_reg_to_mC(regval); break; default: - return -EOPNOTSUPP; + return -EINVAL; } + return 0; +} + +static int tmp102_update_interval(struct device *dev, long val) +{ + struct tmp102 *tmp102 =3D dev_get_drvdata(dev); + unsigned int reg; + u8 index; + s32 err; + + index =3D find_closest(val, tmp102->params->sample_times, + (int)tmp102->params->num_sample_times); =20 - err =3D regmap_read(tmp102->regmap, reg, ®val); + err =3D regmap_read(tmp102->regmap, TMP102_CONF_REG, ®); + if (err < 0) + return err; + reg &=3D ~0x00c0; + reg |=3D (3 - index) << 6; + err =3D regmap_write(tmp102->regmap, TMP102_CONF_REG, reg); if (err < 0) return err; - *temp =3D tmp102_reg_to_mC(regval); + tmp102->sample_time =3D tmp102->params->sample_times[index]; =20 return 0; } =20 +static int tmp102_write_chip(struct device *dev, u32 attr, long val) +{ + switch (attr) { + case hwmon_chip_update_interval: + return tmp102_update_interval(dev, val); + default: + return -EINVAL; + } + return 0; +} + static int tmp102_write(struct device *dev, enum hwmon_sensor_types type, - u32 attr, int channel, long temp) + u32 attr, int channel, long val) { struct tmp102 *tmp102 =3D dev_get_drvdata(dev); int reg; =20 - switch (attr) { - case hwmon_temp_max_hyst: - reg =3D TMP102_TLOW_REG; - break; - case hwmon_temp_max: - reg =3D TMP102_THIGH_REG; - break; + switch (type) { + case hwmon_chip: + return tmp102_write_chip(dev, attr, val); + case hwmon_temp: + switch (attr) { + case hwmon_temp_max_hyst: + reg =3D TMP102_TLOW_REG; + break; + case hwmon_temp_max: + reg =3D TMP102_THIGH_REG; + break; + default: + return -EOPNOTSUPP; + } + + val =3D clamp_val(val, -256000, 255000); + return regmap_write(tmp102->regmap, reg, tmp102_mC_to_reg(val)); default: - return -EOPNOTSUPP; + return -EINVAL; } - - temp =3D clamp_val(temp, -256000, 255000); - return regmap_write(tmp102->regmap, reg, tmp102_mC_to_reg(temp)); + return 0; } =20 static umode_t tmp102_is_visible(const void *data, enum hwmon_sensor_types= type, @@ -139,27 +208,35 @@ static umode_t tmp102_is_visible(const void *data, en= um hwmon_sensor_types type, { const struct tmp102 *tmp102 =3D data; =20 - if (type !=3D hwmon_temp) - return 0; - - switch (attr) { - case hwmon_temp_input: - return 0444; - case hwmon_temp_label: - if (tmp102->label) + switch (type) { + case hwmon_chip: + switch (attr) { + case hwmon_chip_update_interval: + return 0644; + } + break; + case hwmon_temp: + switch (attr) { + case hwmon_temp_input: return 0444; - return 0; - case hwmon_temp_max_hyst: - case hwmon_temp_max: - return 0644; + case hwmon_temp_label: + if (tmp102->label) + return 0444; + return 0; + case hwmon_temp_max_hyst: + case hwmon_temp_max: + return 0644; + } + break; default: - return 0; + break; } + return 0; } =20 static const struct hwmon_channel_info * const tmp102_info[] =3D { HWMON_CHANNEL_INFO(chip, - HWMON_C_REGISTER_TZ), + HWMON_C_REGISTER_TZ | HWMON_C_UPDATE_INTERVAL), HWMON_CHANNEL_INFO(temp, HWMON_T_INPUT | HWMON_T_LABEL | HWMON_T_MAX | HWMON_T_MAX_HYST), NULL @@ -237,6 +314,10 @@ static int tmp102_probe(struct i2c_client *client) if (IS_ERR(tmp102->regmap)) return PTR_ERR(tmp102->regmap); =20 + tmp102->params =3D &device_params; + + tmp102->sample_time =3D tmp102->params->default_sample_time; + err =3D regmap_read(tmp102->regmap, TMP102_CONF_REG, ®val); if (err < 0) { dev_err(dev, "error reading config register\n"); --=20 2.34.1