* [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
* 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 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
* [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 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