linux-hwmon.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v2 0/3] hwmon: scmi: Scale values to target desired HWMON units
@ 2019-05-07 19:35 Florian Fainelli
  2019-05-07 19:35 ` [PATCH v2 1/3] kernel: Provide a __pow10() function Florian Fainelli
                   ` (2 more replies)
  0 siblings, 3 replies; 8+ messages in thread
From: Florian Fainelli @ 2019-05-07 19:35 UTC (permalink / raw)
  To: linux-kernel
  Cc: Florian Fainelli, Sudeep Holla, Jean Delvare, Guenter Roeck,
	linux-arm-kernel, open list:HARDWARE MONITORING,
	bcm-kernel-feedback-list

Hi Sudeep, Guenter,

This patch series adds support for scaling SCMI sensor values read from
firmware. Sudeep, let me know if you think we should be treating scale
== 0 as a special value to preserve some firmware compatibility (not
that this would be desired).

Changes in v2:

- added a helper function in kernel.h: __pow10()
- made the scale in scmi_sensor_info an s8 type, added defines for
  checking the sign bit and sign extending with a mask
- simplify computations in hwmon driver

Florian Fainelli (3):
  kernel: Provide a __pow10() function
  firmware: arm_scmi: Fetch and store sensor scale
  hwmon: scmi: Scale values to target desired HWMON units

 drivers/firmware/arm_scmi/sensors.c |  6 ++++++
 drivers/hwmon/scmi-hwmon.c          | 30 ++++++++++++++++++++++++++++-
 include/linux/kernel.h              | 11 +++++++++++
 include/linux/scmi_protocol.h       |  1 +
 4 files changed, 47 insertions(+), 1 deletion(-)

-- 
2.17.1


^ permalink raw reply	[flat|nested] 8+ messages in thread

* [PATCH v2 1/3] kernel: Provide a __pow10() function
  2019-05-07 19:35 [PATCH v2 0/3] hwmon: scmi: Scale values to target desired HWMON units Florian Fainelli
@ 2019-05-07 19:35 ` Florian Fainelli
  2019-05-07 21:06   ` Guenter Roeck
  2019-05-07 19:35 ` [PATCH v2 2/3] firmware: arm_scmi: Fetch and store sensor scale Florian Fainelli
  2019-05-07 19:35 ` [PATCH v2 3/3] hwmon: scmi: Scale values to target desired HWMON units Florian Fainelli
  2 siblings, 1 reply; 8+ messages in thread
From: Florian Fainelli @ 2019-05-07 19:35 UTC (permalink / raw)
  To: linux-kernel
  Cc: Florian Fainelli, Sudeep Holla, Jean Delvare, Guenter Roeck,
	linux-arm-kernel, open list:HARDWARE MONITORING,
	bcm-kernel-feedback-list

Provide a simple macro that can return the value of 10 raised to a
positive integer. We are going to use this in order to scale units from
firmware to HWMON.

Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
---
 include/linux/kernel.h | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/include/linux/kernel.h b/include/linux/kernel.h
index 2d14e21c16c0..62fc8bd84bc9 100644
--- a/include/linux/kernel.h
+++ b/include/linux/kernel.h
@@ -294,6 +294,17 @@ static inline u32 reciprocal_scale(u32 val, u32 ep_ro)
 	return (u32)(((u64) val * ep_ro) >> 32);
 }
 
+/* Return in f the value of 10 raise to the power x */
+#define __pow10(x, f)(					\
+{							\
+	typeof(x) __x = abs(x);				\
+	f = 1;						\
+	while (__x--)					\
+		f *= 10;				\
+	f;						\
+}							\
+)
+
 #if defined(CONFIG_MMU) && \
 	(defined(CONFIG_PROVE_LOCKING) || defined(CONFIG_DEBUG_ATOMIC_SLEEP))
 #define might_fault() __might_fault(__FILE__, __LINE__)
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH v2 2/3] firmware: arm_scmi: Fetch and store sensor scale
  2019-05-07 19:35 [PATCH v2 0/3] hwmon: scmi: Scale values to target desired HWMON units Florian Fainelli
  2019-05-07 19:35 ` [PATCH v2 1/3] kernel: Provide a __pow10() function Florian Fainelli
@ 2019-05-07 19:35 ` Florian Fainelli
  2019-05-07 19:35 ` [PATCH v2 3/3] hwmon: scmi: Scale values to target desired HWMON units Florian Fainelli
  2 siblings, 0 replies; 8+ messages in thread
From: Florian Fainelli @ 2019-05-07 19:35 UTC (permalink / raw)
  To: linux-kernel
  Cc: Florian Fainelli, Sudeep Holla, Jean Delvare, Guenter Roeck,
	linux-arm-kernel, open list:HARDWARE MONITORING,
	bcm-kernel-feedback-list

In preparation for dealing with scales within the SCMI HWMON driver,
fetch and store the sensor unit scale into the scmi_sensor_info
structure. In order to simplify computations for upper layer, take care
of sign extending the scale to a full 8-bit signed value.

Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
---
 drivers/firmware/arm_scmi/sensors.c | 6 ++++++
 include/linux/scmi_protocol.h       | 1 +
 2 files changed, 7 insertions(+)

diff --git a/drivers/firmware/arm_scmi/sensors.c b/drivers/firmware/arm_scmi/sensors.c
index b53d5cc9c9f6..21353470a740 100644
--- a/drivers/firmware/arm_scmi/sensors.c
+++ b/drivers/firmware/arm_scmi/sensors.c
@@ -34,6 +34,8 @@ struct scmi_msg_resp_sensor_description {
 		__le32 attributes_high;
 #define SENSOR_TYPE(x)		((x) & 0xff)
 #define SENSOR_SCALE(x)		(((x) >> 11) & 0x3f)
+#define SENSOR_SCALE_SIGN	BIT(5)
+#define SENSOR_SCALE_EXTEND	GENMASK(7, 6)
 #define SENSOR_UPDATE_SCALE(x)	(((x) >> 22) & 0x1f)
 #define SENSOR_UPDATE_BASE(x)	(((x) >> 27) & 0x1f)
 		    u8 name[SCMI_MAX_STR_SIZE];
@@ -140,6 +142,10 @@ static int scmi_sensor_description_get(const struct scmi_handle *handle,
 			s = &si->sensors[desc_index + cnt];
 			s->id = le32_to_cpu(buf->desc[cnt].id);
 			s->type = SENSOR_TYPE(attrh);
+			s->scale = SENSOR_SCALE(attrh);
+			/* Sign extend to a full s8 */
+			if (s->scale & SENSOR_SCALE_SIGN)
+				s->scale |= SENSOR_SCALE_EXTEND;
 			strlcpy(s->name, buf->desc[cnt].name, SCMI_MAX_STR_SIZE);
 		}
 
diff --git a/include/linux/scmi_protocol.h b/include/linux/scmi_protocol.h
index 3105055c00a7..9ff2e9357e9a 100644
--- a/include/linux/scmi_protocol.h
+++ b/include/linux/scmi_protocol.h
@@ -144,6 +144,7 @@ struct scmi_power_ops {
 struct scmi_sensor_info {
 	u32 id;
 	u8 type;
+	s8 scale;
 	char name[SCMI_MAX_STR_SIZE];
 };
 
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH v2 3/3] hwmon: scmi: Scale values to target desired HWMON units
  2019-05-07 19:35 [PATCH v2 0/3] hwmon: scmi: Scale values to target desired HWMON units Florian Fainelli
  2019-05-07 19:35 ` [PATCH v2 1/3] kernel: Provide a __pow10() function Florian Fainelli
  2019-05-07 19:35 ` [PATCH v2 2/3] firmware: arm_scmi: Fetch and store sensor scale Florian Fainelli
@ 2019-05-07 19:35 ` Florian Fainelli
  2019-05-07 21:14   ` Guenter Roeck
  2 siblings, 1 reply; 8+ messages in thread
From: Florian Fainelli @ 2019-05-07 19:35 UTC (permalink / raw)
  To: linux-kernel
  Cc: Florian Fainelli, Sudeep Holla, Jean Delvare, Guenter Roeck,
	linux-arm-kernel, open list:HARDWARE MONITORING,
	bcm-kernel-feedback-list

If the SCMI firmware implementation is reporting values in a scale that
is different from the HWMON units, we need to scale up or down the value
according to how far appart they are.

Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
---
 drivers/hwmon/scmi-hwmon.c | 30 +++++++++++++++++++++++++++++-
 1 file changed, 29 insertions(+), 1 deletion(-)

diff --git a/drivers/hwmon/scmi-hwmon.c b/drivers/hwmon/scmi-hwmon.c
index a80183a488c5..5c244053efc8 100644
--- a/drivers/hwmon/scmi-hwmon.c
+++ b/drivers/hwmon/scmi-hwmon.c
@@ -18,6 +18,34 @@ struct scmi_sensors {
 	const struct scmi_sensor_info **info[hwmon_max];
 };
 
+static u64 scmi_hwmon_scale(const struct scmi_sensor_info *sensor, u64 value)
+{
+	s8 scale = sensor->scale;
+	unsigned long long f;
+
+	switch (sensor->type) {
+	case TEMPERATURE_C:
+	case VOLTAGE:
+	case CURRENT:
+		scale += 3;
+		break;
+	case POWER:
+	case ENERGY:
+		scale += 6;
+		break;
+	default:
+		break;
+	}
+
+	__pow10(abs(scale), f);
+	if (scale > 0)
+		value *= f;
+	else
+		do_div(value, f);
+
+        return value;
+}
+
 static int scmi_hwmon_read(struct device *dev, enum hwmon_sensor_types type,
 			   u32 attr, int channel, long *val)
 {
@@ -30,7 +58,7 @@ static int scmi_hwmon_read(struct device *dev, enum hwmon_sensor_types type,
 	sensor = *(scmi_sensors->info[type] + channel);
 	ret = h->sensor_ops->reading_get(h, sensor->id, false, &value);
 	if (!ret)
-		*val = value;
+		*val = scmi_hwmon_scale(sensor, value);
 
 	return ret;
 }
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* Re: [PATCH v2 1/3] kernel: Provide a __pow10() function
  2019-05-07 19:35 ` [PATCH v2 1/3] kernel: Provide a __pow10() function Florian Fainelli
@ 2019-05-07 21:06   ` Guenter Roeck
  2019-05-07 21:49     ` Florian Fainelli
  0 siblings, 1 reply; 8+ messages in thread
From: Guenter Roeck @ 2019-05-07 21:06 UTC (permalink / raw)
  To: Florian Fainelli
  Cc: linux-kernel, Sudeep Holla, Jean Delvare, linux-arm-kernel,
	open list:HARDWARE MONITORING, bcm-kernel-feedback-list

On Tue, May 07, 2019 at 12:35:02PM -0700, Florian Fainelli wrote:
> Provide a simple macro that can return the value of 10 raised to a
> positive integer. We are going to use this in order to scale units from
> firmware to HWMON.
> 
> Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
> ---
>  include/linux/kernel.h | 11 +++++++++++
>  1 file changed, 11 insertions(+)
> 
> diff --git a/include/linux/kernel.h b/include/linux/kernel.h
> index 2d14e21c16c0..62fc8bd84bc9 100644
> --- a/include/linux/kernel.h
> +++ b/include/linux/kernel.h
> @@ -294,6 +294,17 @@ static inline u32 reciprocal_scale(u32 val, u32 ep_ro)
>  	return (u32)(((u64) val * ep_ro) >> 32);
>  }
>  
> +/* Return in f the value of 10 raise to the power x */
> +#define __pow10(x, f)(					\
> +{							\
> +	typeof(x) __x = abs(x);				\
> +	f = 1;						\
> +	while (__x--)					\
> +		f *= 10;				\
> +	f;						\
> +}							\
> +)

Kind of unusual. I would have expected to use this like
	f = __pow10(x);
ie without having to provide f as parameter. That would be much less
confusing. I assume this is to make the result type independent, but
I am not sure if that is worth the trouble.

Are there users outside the hwmon code ? If not, it might be simpler
to keep it there for now.

Thanks,
Guenter

> +
>  #if defined(CONFIG_MMU) && \
>  	(defined(CONFIG_PROVE_LOCKING) || defined(CONFIG_DEBUG_ATOMIC_SLEEP))
>  #define might_fault() __might_fault(__FILE__, __LINE__)
> -- 
> 2.17.1
> 

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH v2 3/3] hwmon: scmi: Scale values to target desired HWMON units
  2019-05-07 19:35 ` [PATCH v2 3/3] hwmon: scmi: Scale values to target desired HWMON units Florian Fainelli
@ 2019-05-07 21:14   ` Guenter Roeck
  0 siblings, 0 replies; 8+ messages in thread
From: Guenter Roeck @ 2019-05-07 21:14 UTC (permalink / raw)
  To: Florian Fainelli
  Cc: linux-kernel, Sudeep Holla, Jean Delvare, linux-arm-kernel,
	open list:HARDWARE MONITORING, bcm-kernel-feedback-list

On Tue, May 07, 2019 at 12:35:04PM -0700, Florian Fainelli wrote:
> If the SCMI firmware implementation is reporting values in a scale that
> is different from the HWMON units, we need to scale up or down the value
> according to how far appart they are.
> 
> Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
> ---
>  drivers/hwmon/scmi-hwmon.c | 30 +++++++++++++++++++++++++++++-
>  1 file changed, 29 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/hwmon/scmi-hwmon.c b/drivers/hwmon/scmi-hwmon.c
> index a80183a488c5..5c244053efc8 100644
> --- a/drivers/hwmon/scmi-hwmon.c
> +++ b/drivers/hwmon/scmi-hwmon.c
> @@ -18,6 +18,34 @@ struct scmi_sensors {
>  	const struct scmi_sensor_info **info[hwmon_max];
>  };
>  
> +static u64 scmi_hwmon_scale(const struct scmi_sensor_info *sensor, u64 value)
> +{
> +	s8 scale = sensor->scale;
> +	unsigned long long f;

do_div() takes either an uint32 or an unsigned long as second parameter,
so this doesn't really help. If you want to be able to handle scales
outside the 32-bit range, you would have to use u64 and div64_u64().

Guenter

> +
> +	switch (sensor->type) {
> +	case TEMPERATURE_C:
> +	case VOLTAGE:
> +	case CURRENT:
> +		scale += 3;
> +		break;
> +	case POWER:
> +	case ENERGY:
> +		scale += 6;
> +		break;
> +	default:
> +		break;
> +	}
> +
> +	__pow10(abs(scale), f);
> +	if (scale > 0)
> +		value *= f;
> +	else
> +		do_div(value, f);
> +
> +        return value;
> +}
> +
>  static int scmi_hwmon_read(struct device *dev, enum hwmon_sensor_types type,
>  			   u32 attr, int channel, long *val)
>  {
> @@ -30,7 +58,7 @@ static int scmi_hwmon_read(struct device *dev, enum hwmon_sensor_types type,
>  	sensor = *(scmi_sensors->info[type] + channel);
>  	ret = h->sensor_ops->reading_get(h, sensor->id, false, &value);
>  	if (!ret)
> -		*val = value;
> +		*val = scmi_hwmon_scale(sensor, value);
>  
>  	return ret;
>  }
> -- 
> 2.17.1
> 

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH v2 1/3] kernel: Provide a __pow10() function
  2019-05-07 21:06   ` Guenter Roeck
@ 2019-05-07 21:49     ` Florian Fainelli
  2019-05-07 23:21       ` Guenter Roeck
  0 siblings, 1 reply; 8+ messages in thread
From: Florian Fainelli @ 2019-05-07 21:49 UTC (permalink / raw)
  To: Guenter Roeck, Florian Fainelli
  Cc: linux-kernel, Sudeep Holla, Jean Delvare, linux-arm-kernel,
	open list:HARDWARE MONITORING, bcm-kernel-feedback-list

On 5/7/19 2:06 PM, Guenter Roeck wrote:
> On Tue, May 07, 2019 at 12:35:02PM -0700, Florian Fainelli wrote:
>> Provide a simple macro that can return the value of 10 raised to a
>> positive integer. We are going to use this in order to scale units from
>> firmware to HWMON.
>>
>> Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
>> ---
>>  include/linux/kernel.h | 11 +++++++++++
>>  1 file changed, 11 insertions(+)
>>
>> diff --git a/include/linux/kernel.h b/include/linux/kernel.h
>> index 2d14e21c16c0..62fc8bd84bc9 100644
>> --- a/include/linux/kernel.h
>> +++ b/include/linux/kernel.h
>> @@ -294,6 +294,17 @@ static inline u32 reciprocal_scale(u32 val, u32 ep_ro)
>>  	return (u32)(((u64) val * ep_ro) >> 32);
>>  }
>>  
>> +/* Return in f the value of 10 raise to the power x */
>> +#define __pow10(x, f)(					\
>> +{							\
>> +	typeof(x) __x = abs(x);				\
>> +	f = 1;						\
>> +	while (__x--)					\
>> +		f *= 10;				\
>> +	f;						\
>> +}							\
>> +)
> 
> Kind of unusual. I would have expected to use this like
> 	f = __pow10(x);
> ie without having to provide f as parameter. That would be much less
> confusing. I assume this is to make the result type independent, but
> I am not sure if that is worth the trouble.

Correct, that was the intent here.

> 
> Are there users outside the hwmon code ? If not, it might be simpler
> to keep it there for now.

There appears to be a few outside actually:

drivers/acpi/sbs.c::battery_scale
drivers/iio/common/hid-sensors/hid-sensor-attributes.c::pow_10

There could be others but those two came out as obvious candidates.

Would you be okay with a local pow10 function within scmi-hwmon.c and a
subsequent patch series providing a common function?
-- 
Florian

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH v2 1/3] kernel: Provide a __pow10() function
  2019-05-07 21:49     ` Florian Fainelli
@ 2019-05-07 23:21       ` Guenter Roeck
  0 siblings, 0 replies; 8+ messages in thread
From: Guenter Roeck @ 2019-05-07 23:21 UTC (permalink / raw)
  To: Florian Fainelli
  Cc: linux-kernel, Sudeep Holla, Jean Delvare, linux-arm-kernel,
	open list:HARDWARE MONITORING, bcm-kernel-feedback-list

On 5/7/19 2:49 PM, Florian Fainelli wrote:
> On 5/7/19 2:06 PM, Guenter Roeck wrote:
>> On Tue, May 07, 2019 at 12:35:02PM -0700, Florian Fainelli wrote:
>>> Provide a simple macro that can return the value of 10 raised to a
>>> positive integer. We are going to use this in order to scale units from
>>> firmware to HWMON.
>>>
>>> Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
>>> ---
>>>   include/linux/kernel.h | 11 +++++++++++
>>>   1 file changed, 11 insertions(+)
>>>
>>> diff --git a/include/linux/kernel.h b/include/linux/kernel.h
>>> index 2d14e21c16c0..62fc8bd84bc9 100644
>>> --- a/include/linux/kernel.h
>>> +++ b/include/linux/kernel.h
>>> @@ -294,6 +294,17 @@ static inline u32 reciprocal_scale(u32 val, u32 ep_ro)
>>>   	return (u32)(((u64) val * ep_ro) >> 32);
>>>   }
>>>   
>>> +/* Return in f the value of 10 raise to the power x */
>>> +#define __pow10(x, f)(					\
>>> +{							\
>>> +	typeof(x) __x = abs(x);				\
>>> +	f = 1;						\
>>> +	while (__x--)					\
>>> +		f *= 10;				\
>>> +	f;						\
>>> +}							\
>>> +)
>>
>> Kind of unusual. I would have expected to use this like
>> 	f = __pow10(x);
>> ie without having to provide f as parameter. That would be much less
>> confusing. I assume this is to make the result type independent, but
>> I am not sure if that is worth the trouble.
> 
> Correct, that was the intent here.
> 
>>
>> Are there users outside the hwmon code ? If not, it might be simpler
>> to keep it there for now.
> 
> There appears to be a few outside actually:
> 
> drivers/acpi/sbs.c::battery_scale
> drivers/iio/common/hid-sensors/hid-sensor-attributes.c::pow_10
> 
> There could be others but those two came out as obvious candidates.
> 
> Would you be okay with a local pow10 function within scmi-hwmon.c and a
> subsequent patch series providing a common function?
> 

I would prefer that, actually, to reduce dependencies.

Thanks,
Guenter

^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2019-05-07 23:21 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-05-07 19:35 [PATCH v2 0/3] hwmon: scmi: Scale values to target desired HWMON units Florian Fainelli
2019-05-07 19:35 ` [PATCH v2 1/3] kernel: Provide a __pow10() function Florian Fainelli
2019-05-07 21:06   ` Guenter Roeck
2019-05-07 21:49     ` Florian Fainelli
2019-05-07 23:21       ` Guenter Roeck
2019-05-07 19:35 ` [PATCH v2 2/3] firmware: arm_scmi: Fetch and store sensor scale Florian Fainelli
2019-05-07 19:35 ` [PATCH v2 3/3] hwmon: scmi: Scale values to target desired HWMON units Florian Fainelli
2019-05-07 21:14   ` Guenter Roeck

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).