1 From 994102ee967232e7565887d2a5fb83384b550bd8 Mon Sep 17 00:00:00 2001
2 From: Cristian Marussi <cristian.marussi@arm.com>
3 Date: Thu, 19 Nov 2020 17:49:02 +0000
4 Subject: [PATCH] firmware: arm_scmi: add SCMIv3.0 Sensors descriptors
7 Add support for new SCMIv3.0 Sensors extensions related to new sensors'
8 features, like multiple axis and update intervals, while keeping
9 compatibility with SCMIv2.0 features.
10 While at that, refactor and simplify all the internal helpers macros and
11 move struct scmi_sensor_info to use only non-fixed-size typing.
13 Signed-off-by: Cristian Marussi <cristian.marussi@arm.com>
14 Signed-off-by: Vasyl Vavrychuk <vasyl.vavrychuk@opensynergy.com>
16 drivers/firmware/arm_scmi/sensors.c | 390 ++++++++++++++++++++++++++--
17 include/linux/scmi_protocol.h | 220 +++++++++++++++-
18 2 files changed, 585 insertions(+), 25 deletions(-)
20 diff --git a/drivers/firmware/arm_scmi/sensors.c b/drivers/firmware/arm_scmi/sensors.c
21 index 6aaff478d032..a85827f60a02 100644
22 --- a/drivers/firmware/arm_scmi/sensors.c
23 +++ b/drivers/firmware/arm_scmi/sensors.c
26 #define pr_fmt(fmt) "SCMI Notifications SENSOR - " fmt
28 +#include <linux/bitfield.h>
29 #include <linux/scmi_protocol.h>
34 +#define SCMI_MAX_NUM_SENSOR_AXIS 63
35 +#define SCMIv2_SENSOR_PROTOCOL 0x10000
37 enum scmi_sensor_protocol_cmd {
38 SENSOR_DESCRIPTION_GET = 0x3,
39 SENSOR_TRIP_POINT_NOTIFY = 0x4,
40 SENSOR_TRIP_POINT_CONFIG = 0x5,
41 SENSOR_READING_GET = 0x6,
42 + SENSOR_AXIS_DESCRIPTION_GET = 0x7,
43 + SENSOR_LIST_UPDATE_INTERVALS = 0x8,
46 struct scmi_msg_resp_sensor_attributes {
47 @@ -28,23 +34,100 @@ struct scmi_msg_resp_sensor_attributes {
51 +/* v3 attributes_low macros */
52 +#define SUPPORTS_UPDATE_NOTIFY(x) FIELD_GET(BIT(30), (x))
53 +#define SENSOR_TSTAMP_EXP(x) FIELD_GET(GENMASK(14, 10), (x))
54 +#define SUPPORTS_TIMESTAMP(x) FIELD_GET(BIT(9), (x))
55 +#define SUPPORTS_EXTEND_ATTRS(x) FIELD_GET(BIT(8), (x))
57 +/* v2 attributes_high macros */
58 +#define SENSOR_UPDATE_BASE(x) FIELD_GET(GENMASK(31, 27), (x))
59 +#define SENSOR_UPDATE_SCALE(x) FIELD_GET(GENMASK(26, 22), (x))
61 +/* v3 attributes_high macros */
62 +#define SENSOR_AXIS_NUMBER(x) FIELD_GET(GENMASK(21, 16), (x))
63 +#define SUPPORTS_AXIS(x) FIELD_GET(BIT(8), (x))
65 +/* v3 resolution macros */
66 +#define SENSOR_RES(x) FIELD_GET(GENMASK(26, 0), (x))
67 +#define SENSOR_RES_EXP(x) FIELD_GET(GENMASK(31, 27), (x))
69 +struct scmi_msg_resp_attrs {
70 + __le32 min_range_low;
71 + __le32 min_range_high;
72 + __le32 max_range_low;
73 + __le32 max_range_high;
76 struct scmi_msg_resp_sensor_description {
80 + struct scmi_sensor_descriptor {
82 + __le32 attributes_low;
83 +/* Common attributes_low macros */
84 +#define SUPPORTS_ASYNC_READ(x) FIELD_GET(BIT(31), (x))
85 +#define NUM_TRIP_POINTS(x) FIELD_GET(GENMASK(7, 0), (x))
86 + __le32 attributes_high;
87 +/* Common attributes_high macros */
88 +#define SENSOR_SCALE(x) FIELD_GET(GENMASK(15, 11), (x))
89 +#define SENSOR_SCALE_SIGN BIT(4)
90 +#define SENSOR_SCALE_EXTEND GENMASK(31, 5)
91 +#define SENSOR_TYPE(x) FIELD_GET(GENMASK(7, 0), (x))
92 + u8 name[SCMI_MAX_STR_SIZE];
93 + /* only for version > 2.0 */
96 + struct scmi_msg_resp_attrs scalar_attrs;
100 +/* Base scmi_sensor_descriptor size excluding extended attrs after name */
101 +#define SCMI_MSG_RESP_SENS_DESCR_BASE_SZ 28
103 +/* Sign extend to a full s32 */
104 +#define S32_EXT(v) \
108 + if (__v & SENSOR_SCALE_SIGN) \
109 + __v |= SENSOR_SCALE_EXTEND; \
113 +struct scmi_msg_sensor_axis_description_get {
115 + __le32 axis_desc_index;
118 +struct scmi_msg_resp_sensor_axis_description {
119 + __le32 num_axis_flags;
120 +#define NUM_AXIS_RETURNED(x) FIELD_GET(GENMASK(5, 0), (x))
121 +#define NUM_AXIS_REMAINING(x) FIELD_GET(GENMASK(31, 26), (x))
122 + struct scmi_axis_descriptor {
124 __le32 attributes_low;
125 -#define SUPPORTS_ASYNC_READ(x) ((x) & BIT(31))
126 -#define NUM_TRIP_POINTS(x) ((x) & 0xff)
127 __le32 attributes_high;
128 -#define SENSOR_TYPE(x) ((x) & 0xff)
129 -#define SENSOR_SCALE(x) (((x) >> 11) & 0x1f)
130 -#define SENSOR_SCALE_SIGN BIT(4)
131 -#define SENSOR_SCALE_EXTEND GENMASK(7, 5)
132 -#define SENSOR_UPDATE_SCALE(x) (((x) >> 22) & 0x1f)
133 -#define SENSOR_UPDATE_BASE(x) (((x) >> 27) & 0x1f)
134 - u8 name[SCMI_MAX_STR_SIZE];
136 + u8 name[SCMI_MAX_STR_SIZE];
138 + struct scmi_msg_resp_attrs attrs;
142 +/* Base scmi_axis_descriptor size excluding extended attrs after name */
143 +#define SCMI_MSG_RESP_AXIS_DESCR_BASE_SZ 28
145 +struct scmi_msg_sensor_list_update_intervals {
150 +struct scmi_msg_resp_sensor_list_update_intervals {
151 + __le32 num_intervals_flags;
152 +#define NUM_INTERVALS_RETURNED(x) FIELD_GET(GENMASK(11, 0), (x))
153 +#define SEGMENTED_INTVL_FORMAT(x) FIELD_GET(BIT(12), (x))
154 +#define NUM_INTERVALS_REMAINING(x) FIELD_GET(GENMASK(31, 16), (x))
155 + __le32 intervals[];
158 struct scmi_msg_sensor_trip_point_notify {
159 @@ -114,6 +197,194 @@ static int scmi_sensor_attributes_get(const struct scmi_handle *handle,
163 +static inline void scmi_parse_range_attrs(struct scmi_range_attrs *out,
164 + struct scmi_msg_resp_attrs *in)
166 + out->min_range = get_unaligned_le64((void *)&in->min_range_low);
167 + out->max_range = get_unaligned_le64((void *)&in->max_range_low);
170 +static int scmi_sensor_update_intervals(const struct scmi_handle *handle,
171 + struct scmi_sensor_info *s)
174 + u32 desc_index = 0;
175 + u16 num_returned, num_remaining;
176 + struct scmi_xfer *ti;
177 + struct scmi_msg_resp_sensor_list_update_intervals *buf;
178 + struct scmi_msg_sensor_list_update_intervals *msg;
180 + ret = scmi_xfer_get_init(handle, SENSOR_LIST_UPDATE_INTERVALS,
181 + SCMI_PROTOCOL_SENSOR, sizeof(*msg), 0, &ti);
190 + /* Set the number of sensors to be skipped/already read */
191 + msg->id = cpu_to_le32(s->id);
192 + msg->index = cpu_to_le32(desc_index);
194 + ret = scmi_do_xfer(handle, ti);
198 + flags = le32_to_cpu(buf->num_intervals_flags);
199 + num_returned = NUM_INTERVALS_RETURNED(flags);
200 + num_remaining = NUM_INTERVALS_REMAINING(flags);
203 + * Max intervals is not declared previously anywhere so we
204 + * assume it's returned+remaining.
206 + if (!s->intervals.count) {
207 + s->intervals.segmented = SEGMENTED_INTVL_FORMAT(flags);
208 + s->intervals.count = num_returned + num_remaining;
209 + /* segmented intervals are reported in one triplet */
210 + if (s->intervals.segmented &&
211 + (num_remaining || num_returned != 3)) {
212 + dev_err(handle->dev,
213 + "Sensor ID:%d advertises an invalid segmented interval (%d)\n",
214 + s->id, s->intervals.count);
215 + s->intervals.segmented = false;
216 + s->intervals.count = 0;
220 + /* Direct allocation when exceeding pre-allocated */
221 + if (s->intervals.count >= SCMI_MAX_PREALLOC_POOL) {
222 + s->intervals.desc =
223 + devm_kcalloc(handle->dev,
224 + s->intervals.count,
225 + sizeof(*s->intervals.desc),
227 + if (!s->intervals.desc) {
228 + s->intervals.segmented = false;
229 + s->intervals.count = 0;
234 + } else if (desc_index + num_returned > s->intervals.count) {
235 + dev_err(handle->dev,
236 + "No. of update intervals can't exceed %d\n",
237 + s->intervals.count);
242 + for (cnt = 0; cnt < num_returned; cnt++)
243 + s->intervals.desc[desc_index + cnt] =
244 + le32_to_cpu(buf->intervals[cnt]);
246 + desc_index += num_returned;
248 + scmi_reset_rx_to_maxsz(handle, ti);
250 + * check for both returned and remaining to avoid infinite
251 + * loop due to buggy firmware
253 + } while (num_returned && num_remaining);
255 + scmi_xfer_put(handle, ti);
259 +static int scmi_sensor_axis_description(const struct scmi_handle *handle,
260 + struct scmi_sensor_info *s)
263 + u32 desc_index = 0;
264 + u16 num_returned, num_remaining;
265 + struct scmi_xfer *te;
266 + struct scmi_msg_resp_sensor_axis_description *buf;
267 + struct scmi_msg_sensor_axis_description_get *msg;
269 + s->axis = devm_kcalloc(handle->dev, s->num_axis,
270 + sizeof(*s->axis), GFP_KERNEL);
274 + ret = scmi_xfer_get_init(handle, SENSOR_AXIS_DESCRIPTION_GET,
275 + SCMI_PROTOCOL_SENSOR, sizeof(*msg), 0, &te);
282 + struct scmi_axis_descriptor *adesc;
285 + /* Set the number of sensors to be skipped/already read */
286 + msg->id = cpu_to_le32(s->id);
287 + msg->axis_desc_index = cpu_to_le32(desc_index);
289 + ret = scmi_do_xfer(handle, te);
293 + flags = le32_to_cpu(buf->num_axis_flags);
294 + num_returned = NUM_AXIS_RETURNED(flags);
295 + num_remaining = NUM_AXIS_REMAINING(flags);
297 + if (desc_index + num_returned > s->num_axis) {
298 + dev_err(handle->dev, "No. of axis can't exceed %d\n",
303 + adesc = &buf->desc[0];
304 + for (cnt = 0; cnt < num_returned; cnt++) {
306 + struct scmi_sensor_axis_info *a;
307 + size_t dsize = SCMI_MSG_RESP_AXIS_DESCR_BASE_SZ;
309 + attrl = le32_to_cpu(adesc->attributes_low);
311 + a = &s->axis[desc_index + cnt];
313 + a->id = le32_to_cpu(adesc->id);
314 + a->extended_attrs = SUPPORTS_EXTEND_ATTRS(attrl);
316 + attrh = le32_to_cpu(adesc->attributes_high);
317 + a->scale = S32_EXT(SENSOR_SCALE(attrh));
318 + a->type = SENSOR_TYPE(attrh);
319 + strlcpy(a->name, adesc->name, SCMI_MAX_STR_SIZE);
321 + if (a->extended_attrs) {
322 + unsigned int ares =
323 + le32_to_cpu(adesc->resolution);
325 + a->resolution = SENSOR_RES(ares);
327 + S32_EXT(SENSOR_RES_EXP(ares));
328 + dsize += sizeof(adesc->resolution);
330 + scmi_parse_range_attrs(&a->attrs,
332 + dsize += sizeof(adesc->attrs);
335 + adesc = (typeof(adesc))((u8 *)adesc + dsize);
338 + desc_index += num_returned;
340 + scmi_reset_rx_to_maxsz(handle, te);
342 + * check for both returned and remaining to avoid infinite
343 + * loop due to buggy firmware
345 + } while (num_returned && num_remaining);
347 + scmi_xfer_put(handle, te);
351 static int scmi_sensor_description_get(const struct scmi_handle *handle,
352 struct sensors_info *si)
354 @@ -131,9 +402,10 @@ static int scmi_sensor_description_get(const struct scmi_handle *handle,
358 + struct scmi_sensor_descriptor *sdesc;
360 /* Set the number of sensors to be skipped/already read */
361 put_unaligned_le32(desc_index, t->tx.buf);
363 ret = scmi_do_xfer(handle, t);
366 @@ -147,22 +419,97 @@ static int scmi_sensor_description_get(const struct scmi_handle *handle,
370 + sdesc = &buf->desc[0];
371 for (cnt = 0; cnt < num_returned; cnt++) {
373 struct scmi_sensor_info *s;
374 + size_t dsize = SCMI_MSG_RESP_SENS_DESCR_BASE_SZ;
376 - attrl = le32_to_cpu(buf->desc[cnt].attributes_low);
377 - attrh = le32_to_cpu(buf->desc[cnt].attributes_high);
378 s = &si->sensors[desc_index + cnt];
379 - s->id = le32_to_cpu(buf->desc[cnt].id);
380 - s->type = SENSOR_TYPE(attrh);
381 - s->scale = SENSOR_SCALE(attrh);
382 - /* Sign extend to a full s8 */
383 - if (s->scale & SENSOR_SCALE_SIGN)
384 - s->scale |= SENSOR_SCALE_EXTEND;
385 + s->id = le32_to_cpu(sdesc->id);
387 + attrl = le32_to_cpu(sdesc->attributes_low);
388 + /* common bitfields parsing */
389 s->async = SUPPORTS_ASYNC_READ(attrl);
390 s->num_trip_points = NUM_TRIP_POINTS(attrl);
391 - strlcpy(s->name, buf->desc[cnt].name, SCMI_MAX_STR_SIZE);
393 + * only SCMIv3.0 specific bitfield below.
394 + * Such bitfields are assumed to be zeroed on non
395 + * relevant fw versions...assuming fw not buggy !
397 + s->update = SUPPORTS_UPDATE_NOTIFY(attrl);
398 + s->timestamped = SUPPORTS_TIMESTAMP(attrl);
399 + if (s->timestamped)
401 + S32_EXT(SENSOR_TSTAMP_EXP(attrl));
402 + s->extended_scalar_attrs =
403 + SUPPORTS_EXTEND_ATTRS(attrl);
405 + attrh = le32_to_cpu(sdesc->attributes_high);
406 + /* common bitfields parsing */
407 + s->scale = S32_EXT(SENSOR_SCALE(attrh));
408 + s->type = SENSOR_TYPE(attrh);
409 + /* Use pre-allocated pool wherever possible */
410 + s->intervals.desc = s->intervals.prealloc_pool;
411 + if (si->version == SCMIv2_SENSOR_PROTOCOL) {
412 + s->intervals.segmented = false;
413 + s->intervals.count = 1;
415 + * Convert SCMIv2.0 update interval format to
416 + * SCMIv3.0 to be used as the common exposed
417 + * descriptor, accessible via common macros.
419 + s->intervals.desc[0] =
420 + (SENSOR_UPDATE_BASE(attrh) << 5) |
421 + SENSOR_UPDATE_SCALE(attrh);
424 + * From SCMIv3.0 update intervals are retrieved
425 + * via a dedicated (optional) command.
426 + * Since the command is optional, on error carry
427 + * on without any update interval.
429 + if (scmi_sensor_update_intervals(handle, s))
430 + dev_dbg(handle->dev,
431 + "Update Intervals not available for sensor ID:%d\n",
435 + * only > SCMIv2.0 specific bitfield below.
436 + * Such bitfields are assumed to be zeroed on non
437 + * relevant fw versions...assuming fw not buggy !
439 + s->num_axis = min_t(unsigned int,
440 + SUPPORTS_AXIS(attrh) ?
441 + SENSOR_AXIS_NUMBER(attrh) : 0,
442 + SCMI_MAX_NUM_SENSOR_AXIS);
443 + strlcpy(s->name, sdesc->name, SCMI_MAX_STR_SIZE);
445 + if (s->extended_scalar_attrs) {
446 + s->sensor_power = le32_to_cpu(sdesc->power);
447 + dsize += sizeof(sdesc->power);
448 + /* Only for sensors reporting scalar values */
449 + if (s->num_axis == 0) {
450 + unsigned int sres =
451 + le32_to_cpu(sdesc->resolution);
453 + s->resolution = SENSOR_RES(sres);
455 + S32_EXT(SENSOR_RES_EXP(sres));
456 + dsize += sizeof(sdesc->resolution);
458 + scmi_parse_range_attrs(&s->scalar_attrs,
459 + &sdesc->scalar_attrs);
460 + dsize += sizeof(sdesc->scalar_attrs);
463 + if (s->num_axis > 0) {
464 + ret = scmi_sensor_axis_description(handle, s);
469 + sdesc = (typeof(sdesc))((u8 *)sdesc + dsize);
472 desc_index += num_returned;
473 @@ -174,6 +521,7 @@ static int scmi_sensor_description_get(const struct scmi_handle *handle,
475 } while (num_returned && num_remaining);
478 scmi_xfer_put(handle, t);
481 diff --git a/include/linux/scmi_protocol.h b/include/linux/scmi_protocol.h
482 index 9cd312a1ff92..0792b0be25a3 100644
483 --- a/include/linux/scmi_protocol.h
484 +++ b/include/linux/scmi_protocol.h
486 #ifndef _LINUX_SCMI_PROTOCOL_H
487 #define _LINUX_SCMI_PROTOCOL_H
489 +#include <linux/bitfield.h>
490 #include <linux/device.h>
491 #include <linux/notifier.h>
492 #include <linux/types.h>
493 @@ -148,13 +149,135 @@ struct scmi_power_ops {
498 + * scmi_range_attrs - specifies a sensor or axis values' range
499 + * @min_range: The minimum value which can be represented by the sensor/axis.
500 + * @max_range: The maximum value which can be represented by the sensor/axis.
502 +struct scmi_range_attrs {
503 + long long min_range;
504 + long long max_range;
508 + * scmi_sensor_axis_info - describes one sensor axes
509 + * @id: The axes ID.
510 + * @type: Axes type. Chosen amongst one of @enum scmi_sensor_class.
511 + * @scale: Power-of-10 multiplier applied to the axis unit.
512 + * @name: NULL-terminated string representing axes name as advertised by
514 + * @extended_attrs: Flag to indicate the presence of additional extended
515 + * attributes for this axes.
516 + * @resolution: Extended attribute representing the resolution of the axes.
517 + * Set to 0 if not reported by this axes.
518 + * @exponent: Extended attribute representing the power-of-10 multiplier that
519 + * is applied to the resolution field. Set to 0 if not reported by
521 + * @attrs: Extended attributes representing minimum and maximum values
522 + * measurable by this axes. Set to 0 if not reported by this sensor.
524 +struct scmi_sensor_axis_info {
528 + char name[SCMI_MAX_STR_SIZE];
529 + bool extended_attrs;
530 + unsigned int resolution;
532 + struct scmi_range_attrs attrs;
536 + * scmi_sensor_intervals_info - describes number and type of available update
538 + * @segmented: Flag for segmented intervals' representation. When True there
539 + * will be exactly 3 intervals in @desc, with each entry
540 + * representing a member of a segment in this order:
541 + * {lowest update interval, highest update interval, step size}
542 + * @count: Number of intervals described in @desc.
543 + * @desc: Array of @count interval descriptor bitmask represented as detailed in
544 + * the SCMI specification: it can be accessed using the accompanying
546 + * @prealloc_pool: A minimal preallocated pool of desc entries used to avoid
547 + * lesser-than-64-bytes dynamic allocation for small @count
550 +struct scmi_sensor_intervals_info {
552 + unsigned int count;
553 +#define SCMI_SENS_INTVL_SEGMENT_LOW 0
554 +#define SCMI_SENS_INTVL_SEGMENT_HIGH 1
555 +#define SCMI_SENS_INTVL_SEGMENT_STEP 2
556 + unsigned int *desc;
557 +#define SCMI_SENS_INTVL_GET_SECS(x) FIELD_GET(GENMASK(20, 5), (x))
558 +#define SCMI_SENS_INTVL_GET_EXP(x) \
560 + int __signed_exp = FIELD_GET(GENMASK(4, 0), (x)); \
562 + if (__signed_exp & BIT(4)) \
563 + __signed_exp |= GENMASK(31, 5); \
566 +#define SCMI_MAX_PREALLOC_POOL 16
567 + unsigned int prealloc_pool[SCMI_MAX_PREALLOC_POOL];
571 + * struct scmi_sensor_info - represents information related to one of the
572 + * available sensors.
574 + * @type: Sensor type. Chosen amongst one of @enum scmi_sensor_class.
575 + * @scale: Power-of-10 multiplier applied to the sensor unit.
576 + * @num_trip_points: Number of maximum configurable trip points.
577 + * @async: Flag for asynchronous read support.
578 + * @update: Flag for continuouos update notification support.
579 + * @timestamped: Flag for timestamped read support.
580 + * @tstamp_scale: Power-of-10 multiplier applied to the sensor timestamps to
581 + * represent it in seconds.
582 + * @num_axis: Number of supported axis if any. Reported as 0 for scalar sensors.
583 + * @axis: Pointer to an array of @num_axis descriptors.
584 + * @intervals: Descriptor of available update intervals.
585 + * @sensor_config: A bitmask reporting the current sensor configuration as
586 + * detailed in the SCMI specification: it can accessed and
587 + * modified through the accompanying macros.
588 + * @name: NULL-terminated string representing sensor name as advertised by
590 + * @extended_scalar_attrs: Flag to indicate the presence of additional extended
591 + * attributes for this sensor.
592 + * @sensor_power: Extended attribute representing the average power
593 + * consumed by the sensor in microwatts (uW) when it is active.
594 + * Reported here only for scalar sensors.
595 + * Set to 0 if not reported by this sensor.
596 + * @resolution: Extended attribute representing the resolution of the sensor.
597 + * Reported here only for scalar sensors.
598 + * Set to 0 if not reported by this sensor.
599 + * @exponent: Extended attribute representing the power-of-10 multiplier that is
600 + * applied to the resolution field.
601 + * Reported here only for scalar sensors.
602 + * Set to 0 if not reported by this sensor.
603 + * @scalar_attrs: Extended attributes representing minimum and maximum
604 + * measurable values by this sensor.
605 + * Reported here only for scalar sensors.
606 + * Set to 0 if not reported by this sensor.
608 struct scmi_sensor_info {
612 - u8 num_trip_points;
616 + unsigned int num_trip_points;
621 + unsigned int num_axis;
622 + struct scmi_sensor_axis_info *axis;
623 + struct scmi_sensor_intervals_info intervals;
624 char name[SCMI_MAX_STR_SIZE];
625 + bool extended_scalar_attrs;
626 + unsigned int sensor_power;
627 + unsigned int resolution;
629 + struct scmi_range_attrs scalar_attrs;
633 @@ -163,11 +286,100 @@ struct scmi_sensor_info {
635 enum scmi_sensor_class {
639 + TEMPERATURE_F = 0x3,
640 + TEMPERATURE_K = 0x4,
665 + CUBIC_INCHES = 0x1D,
669 + CUBIC_METERS = 0x21,
671 + FLUID_OUNCES = 0x23,
674 + REVOLUTIONS = 0x26,
679 + FOOT_POUNDS = 0x2B,
680 + OUNCE_INCHES = 0x2C,
695 + COLOR_TEMP_K = 0x3B,
705 + NEWTON_METERS = 0x45,
716 + CORRECTED_ERRS = 0x50,
717 + UNCORRECTABLE_ERRS = 0x51,
723 + RADIANS_SEC = 0x57,
725 + METERS_SEC_SQUARED = 0x59,
727 + CUBIC_METERS_SEC = 0x5B,
729 + RADIANS_SEC_SQUARED = 0x5D,