From 0ab2c44def8f6cc637a5fb3ce9766d69d2c289d0 Mon Sep 17 00:00:00 2001 From: Volodymyr Babchuk Date: Thu, 23 May 2019 11:23:35 +0000 Subject: [PATCH 1/5] dt-bindings: arm: fix the document ID for SCMI protocol documentation arm,scmi.txt used the wrong document identifier. "ARM DUI 0922B" is the "ARM Compute Subsystem SCP, Message Interface Protocols". What we need is the ARM DEN 0056A - "ARM System Control and Management Interface Platform Design Document". Fixes: fe7be8b297b2 ("dt-bindings: arm: add support for ARM System Control and Management Interface(SCMI) protocol") Signed-off-by: Volodymyr Babchuk Signed-off-by: Sudeep Holla --- Documentation/devicetree/bindings/arm/arm,scmi.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/arm/arm,scmi.txt b/Documentation/devicetree/bindings/arm/arm,scmi.txt index 5f3719ab7075..317a2fc3667a 100644 --- a/Documentation/devicetree/bindings/arm/arm,scmi.txt +++ b/Documentation/devicetree/bindings/arm/arm,scmi.txt @@ -6,7 +6,7 @@ that are provided by the hardware platform it is running on, including power and performance functions. This binding is intended to define the interface the firmware implementing -the SCMI as described in ARM document number ARM DUI 0922B ("ARM System Control +the SCMI as described in ARM document number ARM DEN 0056A ("ARM System Control and Management Interface Platform Design Document")[0] provide for OSPM in the device tree. From 430daaf96ad133be5ce7c3a5c60e94247f7c6f71 Mon Sep 17 00:00:00 2001 From: Sudeep Holla Date: Tue, 14 May 2019 17:10:31 +0100 Subject: [PATCH 2/5] firmware: arm_scmi: fix bitfield definitions for SENSOR_DESC attributes As per the SCMI specification the bitfields for SENSOR_DESC attributes are as follows: attributes_low [7:0] Number of trip points supported attributes_high [15:11] The power-of-10 multiplier in 2's-complement format that is applied to the sensor units Looks like the code developed during the draft versions of the specification slipped through and are wrong with respect to final released version. Fix them by adjusting the bitfields appropriately. Fixes: 5179c523c1ea ("firmware: arm_scmi: add initial support for sensor protocol") Reviewed-by: Florian Fainelli Signed-off-by: Sudeep Holla --- drivers/firmware/arm_scmi/sensors.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/firmware/arm_scmi/sensors.c b/drivers/firmware/arm_scmi/sensors.c index b53d5cc9c9f6..c00287b5f2c2 100644 --- a/drivers/firmware/arm_scmi/sensors.c +++ b/drivers/firmware/arm_scmi/sensors.c @@ -30,10 +30,10 @@ struct scmi_msg_resp_sensor_description { __le32 id; __le32 attributes_low; #define SUPPORTS_ASYNC_READ(x) ((x) & BIT(31)) -#define NUM_TRIP_POINTS(x) (((x) >> 4) & 0xff) +#define NUM_TRIP_POINTS(x) ((x) & 0xff) __le32 attributes_high; #define SENSOR_TYPE(x) ((x) & 0xff) -#define SENSOR_SCALE(x) (((x) >> 11) & 0x3f) +#define SENSOR_SCALE(x) (((x) >> 11) & 0x1f) #define SENSOR_UPDATE_SCALE(x) (((x) >> 22) & 0x1f) #define SENSOR_UPDATE_BASE(x) (((x) >> 27) & 0x1f) u8 name[SCMI_MAX_STR_SIZE]; From c0759b9b5d411ab27c479125cee9bae391a96436 Mon Sep 17 00:00:00 2001 From: Peng Fan Date: Wed, 22 May 2019 10:15:21 +0000 Subject: [PATCH 3/5] firmware: arm_scmi: update rate_discrete in clock_describe_rates_get The boolean rate_discrete needs to be assigned to clk->rate_discrete, so that clock driver can distinguish between the continuous range and discrete rates. It uses this in scmi_clk_round_rate could get the rounded value if it's a continuous range. Fixes: 5f6c6430e904 ("firmware: arm_scmi: add initial support for clock protocol") Signed-off-by: Peng Fan [sudeep.holla: updated commit message] Signed-off-by: Sudeep Holla --- drivers/firmware/arm_scmi/clock.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/firmware/arm_scmi/clock.c b/drivers/firmware/arm_scmi/clock.c index 30fc04e28431..0a194af92438 100644 --- a/drivers/firmware/arm_scmi/clock.c +++ b/drivers/firmware/arm_scmi/clock.c @@ -185,6 +185,8 @@ scmi_clock_describe_rates_get(const struct scmi_handle *handle, u32 clk_id, if (rate_discrete) clk->list.num_rates = tot_rate_cnt; + clk->rate_discrete = rate_discrete; + err: scmi_xfer_put(handle, t); return ret; From 0b673b6486998061b0489b09447ebe8452da0146 Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Wed, 8 May 2019 11:46:34 -0700 Subject: [PATCH 4/5] firmware: arm_scmi: fetch and store sensor scale 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. Reviewed-by: Guenter Roeck Signed-off-by: Florian Fainelli [sudeep.holla: update bitfield values as per specification] Signed-off-by: Sudeep Holla --- 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 c00287b5f2c2..0e94ab56f679 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) & 0x1f) +#define SENSOR_SCALE_SIGN BIT(4) +#define SENSOR_SCALE_EXTEND GENMASK(7, 5) #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]; }; From ac778e62634eee0685b622605b063a49edf2f2d1 Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Wed, 8 May 2019 11:46:35 -0700 Subject: [PATCH 5/5] hwmon: scmi: Scale values to target desired HWMON units 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 apart they are. Reviewed-by: Guenter Roeck Signed-off-by: Florian Fainelli [sudeep.holla: added check of scale = 0 for early exit in scmi_hwmon_scale] Signed-off-by: Sudeep Holla --- drivers/hwmon/scmi-hwmon.c | 48 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/drivers/hwmon/scmi-hwmon.c b/drivers/hwmon/scmi-hwmon.c index a80183a488c5..0c93fc5ca762 100644 --- a/drivers/hwmon/scmi-hwmon.c +++ b/drivers/hwmon/scmi-hwmon.c @@ -18,6 +18,50 @@ struct scmi_sensors { const struct scmi_sensor_info **info[hwmon_max]; }; +static inline u64 __pow10(u8 x) +{ + u64 r = 1; + + while (x--) + r *= 10; + + return r; +} + +static int scmi_hwmon_scale(const struct scmi_sensor_info *sensor, u64 *value) +{ + s8 scale = sensor->scale; + u64 f; + + switch (sensor->type) { + case TEMPERATURE_C: + case VOLTAGE: + case CURRENT: + scale += 3; + break; + case POWER: + case ENERGY: + scale += 6; + break; + default: + break; + } + + if (scale == 0) + return 0; + + if (abs(scale) > 19) + return -E2BIG; + + f = __pow10(abs(scale)); + if (scale > 0) + *value *= f; + else + *value = div64_u64(*value, f); + + return 0; +} + static int scmi_hwmon_read(struct device *dev, enum hwmon_sensor_types type, u32 attr, int channel, long *val) { @@ -29,6 +73,10 @@ 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) + return ret; + + ret = scmi_hwmon_scale(sensor, &value); if (!ret) *val = value;