diff options
author | Olof Johansson <olof@lixom.net> | 2019-06-17 04:54:11 -0700 |
---|---|---|
committer | Olof Johansson <olof@lixom.net> | 2019-06-17 04:54:11 -0700 |
commit | df767c0a437c9094ca2d79d37c1c5cf559039f53 (patch) | |
tree | 37a0b624989bd727ed60cc6025f95ba6b1687e00 | |
parent | c3bd15a0786ef7e32482a7dced21d79286b6f36c (diff) | |
parent | ac778e62634eee0685b622605b063a49edf2f2d1 (diff) | |
download | linux-df767c0a437c9094ca2d79d37c1c5cf559039f53.tar.gz |
Merge tag 'scmi-updates-5.3' of git://git.kernel.org/pub/scm/linux/kernel/git/sudeep.holla/linux into arm/drivers
ARM SCMI updates/fixes for v5.3
1. Correction to ARM document ID referred in SCMI protocol binding
2. Fix to correct bitfield definitions for SENSOR_DESC attributes which
otherwise will calculate sensor values on wrong scale
3. Adds the missing rate_discrete flag setting so that discrete clocks
are handled correctly. Without this fix it assumes continuous range
which is incorrect
4. Adds support to read and scale the sensor values based on the factor
read from the firmware
* tag 'scmi-updates-5.3' of git://git.kernel.org/pub/scm/linux/kernel/git/sudeep.holla/linux:
hwmon: scmi: Scale values to target desired HWMON units
firmware: arm_scmi: fetch and store sensor scale
firmware: arm_scmi: update rate_discrete in clock_describe_rates_get
firmware: arm_scmi: fix bitfield definitions for SENSOR_DESC attributes
dt-bindings: arm: fix the document ID for SCMI protocol documentation
Signed-off-by: Olof Johansson <olof@lixom.net>
-rw-r--r-- | Documentation/devicetree/bindings/arm/arm,scmi.txt | 2 | ||||
-rw-r--r-- | drivers/firmware/arm_scmi/clock.c | 2 | ||||
-rw-r--r-- | drivers/firmware/arm_scmi/sensors.c | 10 | ||||
-rw-r--r-- | drivers/hwmon/scmi-hwmon.c | 48 | ||||
-rw-r--r-- | include/linux/scmi_protocol.h | 1 |
5 files changed, 60 insertions, 3 deletions
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. 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; diff --git a/drivers/firmware/arm_scmi/sensors.c b/drivers/firmware/arm_scmi/sensors.c index b53d5cc9c9f6..0e94ab56f679 100644 --- a/drivers/firmware/arm_scmi/sensors.c +++ b/drivers/firmware/arm_scmi/sensors.c @@ -30,10 +30,12 @@ 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_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/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; 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]; }; |