1 // SPDX-License-Identifier: GPL-2.0
3 * System Control and Management Interface (SCMI) Sensor Protocol
5 * Copyright (C) 2018 ARM Ltd.
10 enum scmi_sensor_protocol_cmd
{
11 SENSOR_DESCRIPTION_GET
= 0x3,
12 SENSOR_CONFIG_SET
= 0x4,
13 SENSOR_TRIP_POINT_SET
= 0x5,
14 SENSOR_READING_GET
= 0x6,
17 struct scmi_msg_resp_sensor_attributes
{
26 struct scmi_msg_resp_sensor_description
{
31 __le32 attributes_low
;
32 #define SUPPORTS_ASYNC_READ(x) ((x) & BIT(31))
33 #define NUM_TRIP_POINTS(x) (((x) >> 4) & 0xff)
34 __le32 attributes_high
;
35 #define SENSOR_TYPE(x) ((x) & 0xff)
36 #define SENSOR_SCALE(x) (((x) >> 11) & 0x3f)
37 #define SENSOR_UPDATE_SCALE(x) (((x) >> 22) & 0x1f)
38 #define SENSOR_UPDATE_BASE(x) (((x) >> 27) & 0x1f)
39 u8 name
[SCMI_MAX_STR_SIZE
];
43 struct scmi_msg_set_sensor_config
{
48 struct scmi_msg_set_sensor_trip_point
{
51 #define SENSOR_TP_EVENT_MASK (0x3)
52 #define SENSOR_TP_DISABLED 0x0
53 #define SENSOR_TP_POSITIVE 0x1
54 #define SENSOR_TP_NEGATIVE 0x2
55 #define SENSOR_TP_BOTH 0x3
56 #define SENSOR_TP_ID(x) (((x) & 0xff) << 4)
61 struct scmi_msg_sensor_reading_get
{
64 #define SENSOR_READ_ASYNC BIT(0)
72 struct scmi_sensor_info
*sensors
;
75 static int scmi_sensor_attributes_get(const struct scmi_handle
*handle
,
76 struct sensors_info
*si
)
80 struct scmi_msg_resp_sensor_attributes
*attr
;
82 ret
= scmi_xfer_get_init(handle
, PROTOCOL_ATTRIBUTES
,
83 SCMI_PROTOCOL_SENSOR
, 0, sizeof(*attr
), &t
);
89 ret
= scmi_do_xfer(handle
, t
);
91 si
->num_sensors
= le16_to_cpu(attr
->num_sensors
);
92 si
->max_requests
= attr
->max_requests
;
93 si
->reg_addr
= le32_to_cpu(attr
->reg_addr_low
) |
94 (u64
)le32_to_cpu(attr
->reg_addr_high
) << 32;
95 si
->reg_size
= le32_to_cpu(attr
->reg_size
);
98 scmi_xfer_put(handle
, t
);
102 static int scmi_sensor_description_get(const struct scmi_handle
*handle
,
103 struct sensors_info
*si
)
107 u16 num_returned
, num_remaining
;
109 struct scmi_msg_resp_sensor_description
*buf
;
111 ret
= scmi_xfer_get_init(handle
, SENSOR_DESCRIPTION_GET
,
112 SCMI_PROTOCOL_SENSOR
, sizeof(__le32
), 0, &t
);
119 /* Set the number of sensors to be skipped/already read */
120 *(__le32
*)t
->tx
.buf
= cpu_to_le32(desc_index
);
122 ret
= scmi_do_xfer(handle
, t
);
126 num_returned
= le16_to_cpu(buf
->num_returned
);
127 num_remaining
= le16_to_cpu(buf
->num_remaining
);
129 if (desc_index
+ num_returned
> si
->num_sensors
) {
130 dev_err(handle
->dev
, "No. of sensors can't exceed %d",
135 for (cnt
= 0; cnt
< num_returned
; cnt
++) {
137 struct scmi_sensor_info
*s
;
139 attrh
= le32_to_cpu(buf
->desc
[cnt
].attributes_high
);
140 s
= &si
->sensors
[desc_index
+ cnt
];
141 s
->id
= le32_to_cpu(buf
->desc
[cnt
].id
);
142 s
->type
= SENSOR_TYPE(attrh
);
143 memcpy(s
->name
, buf
->desc
[cnt
].name
, SCMI_MAX_STR_SIZE
);
146 desc_index
+= num_returned
;
148 * check for both returned and remaining to avoid infinite
149 * loop due to buggy firmware
151 } while (num_returned
&& num_remaining
);
153 scmi_xfer_put(handle
, t
);
158 scmi_sensor_configuration_set(const struct scmi_handle
*handle
, u32 sensor_id
)
161 u32 evt_cntl
= BIT(0);
163 struct scmi_msg_set_sensor_config
*cfg
;
165 ret
= scmi_xfer_get_init(handle
, SENSOR_CONFIG_SET
,
166 SCMI_PROTOCOL_SENSOR
, sizeof(*cfg
), 0, &t
);
171 cfg
->id
= cpu_to_le32(sensor_id
);
172 cfg
->event_control
= cpu_to_le32(evt_cntl
);
174 ret
= scmi_do_xfer(handle
, t
);
176 scmi_xfer_put(handle
, t
);
180 static int scmi_sensor_trip_point_set(const struct scmi_handle
*handle
,
181 u32 sensor_id
, u8 trip_id
, u64 trip_value
)
184 u32 evt_cntl
= SENSOR_TP_BOTH
;
186 struct scmi_msg_set_sensor_trip_point
*trip
;
188 ret
= scmi_xfer_get_init(handle
, SENSOR_TRIP_POINT_SET
,
189 SCMI_PROTOCOL_SENSOR
, sizeof(*trip
), 0, &t
);
194 trip
->id
= cpu_to_le32(sensor_id
);
195 trip
->event_control
= cpu_to_le32(evt_cntl
| SENSOR_TP_ID(trip_id
));
196 trip
->value_low
= cpu_to_le32(trip_value
& 0xffffffff);
197 trip
->value_high
= cpu_to_le32(trip_value
>> 32);
199 ret
= scmi_do_xfer(handle
, t
);
201 scmi_xfer_put(handle
, t
);
205 static int scmi_sensor_reading_get(const struct scmi_handle
*handle
,
206 u32 sensor_id
, bool async
, u64
*value
)
210 struct scmi_msg_sensor_reading_get
*sensor
;
212 ret
= scmi_xfer_get_init(handle
, SENSOR_READING_GET
,
213 SCMI_PROTOCOL_SENSOR
, sizeof(*sensor
),
219 sensor
->id
= cpu_to_le32(sensor_id
);
220 sensor
->flags
= cpu_to_le32(async
? SENSOR_READ_ASYNC
: 0);
222 ret
= scmi_do_xfer(handle
, t
);
224 __le32
*pval
= t
->rx
.buf
;
226 *value
= le32_to_cpu(*pval
);
227 *value
|= (u64
)le32_to_cpu(*(pval
+ 1)) << 32;
230 scmi_xfer_put(handle
, t
);
234 static const struct scmi_sensor_info
*
235 scmi_sensor_info_get(const struct scmi_handle
*handle
, u32 sensor_id
)
237 struct sensors_info
*si
= handle
->sensor_priv
;
239 return si
->sensors
+ sensor_id
;
242 static int scmi_sensor_count_get(const struct scmi_handle
*handle
)
244 struct sensors_info
*si
= handle
->sensor_priv
;
246 return si
->num_sensors
;
249 static struct scmi_sensor_ops sensor_ops
= {
250 .count_get
= scmi_sensor_count_get
,
251 .info_get
= scmi_sensor_info_get
,
252 .configuration_set
= scmi_sensor_configuration_set
,
253 .trip_point_set
= scmi_sensor_trip_point_set
,
254 .reading_get
= scmi_sensor_reading_get
,
257 static int scmi_sensors_protocol_init(struct scmi_handle
*handle
)
260 struct sensors_info
*sinfo
;
262 scmi_version_get(handle
, SCMI_PROTOCOL_SENSOR
, &version
);
264 dev_dbg(handle
->dev
, "Sensor Version %d.%d\n",
265 PROTOCOL_REV_MAJOR(version
), PROTOCOL_REV_MINOR(version
));
267 sinfo
= devm_kzalloc(handle
->dev
, sizeof(*sinfo
), GFP_KERNEL
);
271 scmi_sensor_attributes_get(handle
, sinfo
);
273 sinfo
->sensors
= devm_kcalloc(handle
->dev
, sinfo
->num_sensors
,
274 sizeof(*sinfo
->sensors
), GFP_KERNEL
);
278 scmi_sensor_description_get(handle
, sinfo
);
280 handle
->sensor_ops
= &sensor_ops
;
281 handle
->sensor_priv
= sinfo
;
286 static int __init
scmi_sensors_init(void)
288 return scmi_protocol_register(SCMI_PROTOCOL_SENSOR
,
289 &scmi_sensors_protocol_init
);
291 subsys_initcall(scmi_sensors_init
);