1 // SPDX-License-Identifier: GPL-2.0
2 /*
3 * System Control and Management Interface (SCMI) Sensor Protocol
4 *
5 * Copyright (C) 2018 ARM Ltd.
6 */
7
8 #include "common.h"
9
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,
15 };
16
17 struct scmi_msg_resp_sensor_attributes {
18 __le16 num_sensors;
19 u8 max_requests;
20 u8 reserved;
21 __le32 reg_addr_low;
22 __le32 reg_addr_high;
23 __le32 reg_size;
24 };
25
26 struct scmi_msg_resp_sensor_description {
27 __le16 num_returned;
28 __le16 num_remaining;
29 struct {
30 __le32 id;
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];
40 } desc[0];
41 };
42
43 struct scmi_msg_set_sensor_config {
44 __le32 id;
45 __le32 event_control;
46 };
47
48 struct scmi_msg_set_sensor_trip_point {
49 __le32 id;
50 __le32 event_control;
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)
57 __le32 value_low;
58 __le32 value_high;
59 };
60
61 struct scmi_msg_sensor_reading_get {
62 __le32 id;
63 __le32 flags;
64 #define SENSOR_READ_ASYNC BIT(0)
65 };
66
67 struct sensors_info {
68 int num_sensors;
69 int max_requests;
70 u64 reg_addr;
71 u32 reg_size;
72 struct scmi_sensor_info *sensors;
73 };
74
scmi_sensor_attributes_get(const struct scmi_handle * handle,struct sensors_info * si)75 static int scmi_sensor_attributes_get(const struct scmi_handle *handle,
76 struct sensors_info *si)
77 {
78 int ret;
79 struct scmi_xfer *t;
80 struct scmi_msg_resp_sensor_attributes *attr;
81
82 ret = scmi_xfer_get_init(handle, PROTOCOL_ATTRIBUTES,
83 SCMI_PROTOCOL_SENSOR, 0, sizeof(*attr), &t);
84 if (ret)
85 return ret;
86
87 attr = t->rx.buf;
88
89 ret = scmi_do_xfer(handle, t);
90 if (!ret) {
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);
96 }
97
98 scmi_xfer_put(handle, t);
99 return ret;
100 }
101
scmi_sensor_description_get(const struct scmi_handle * handle,struct sensors_info * si)102 static int scmi_sensor_description_get(const struct scmi_handle *handle,
103 struct sensors_info *si)
104 {
105 int ret, cnt;
106 u32 desc_index = 0;
107 u16 num_returned, num_remaining;
108 struct scmi_xfer *t;
109 struct scmi_msg_resp_sensor_description *buf;
110
111 ret = scmi_xfer_get_init(handle, SENSOR_DESCRIPTION_GET,
112 SCMI_PROTOCOL_SENSOR, sizeof(__le32), 0, &t);
113 if (ret)
114 return ret;
115
116 buf = t->rx.buf;
117
118 do {
119 /* Set the number of sensors to be skipped/already read */
120 *(__le32 *)t->tx.buf = cpu_to_le32(desc_index);
121
122 ret = scmi_do_xfer(handle, t);
123 if (ret)
124 break;
125
126 num_returned = le16_to_cpu(buf->num_returned);
127 num_remaining = le16_to_cpu(buf->num_remaining);
128
129 if (desc_index + num_returned > si->num_sensors) {
130 dev_err(handle->dev, "No. of sensors can't exceed %d",
131 si->num_sensors);
132 break;
133 }
134
135 for (cnt = 0; cnt < num_returned; cnt++) {
136 u32 attrh;
137 struct scmi_sensor_info *s;
138
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);
144 }
145
146 desc_index += num_returned;
147 /*
148 * check for both returned and remaining to avoid infinite
149 * loop due to buggy firmware
150 */
151 } while (num_returned && num_remaining);
152
153 scmi_xfer_put(handle, t);
154 return ret;
155 }
156
157 static int
scmi_sensor_configuration_set(const struct scmi_handle * handle,u32 sensor_id)158 scmi_sensor_configuration_set(const struct scmi_handle *handle, u32 sensor_id)
159 {
160 int ret;
161 u32 evt_cntl = BIT(0);
162 struct scmi_xfer *t;
163 struct scmi_msg_set_sensor_config *cfg;
164
165 ret = scmi_xfer_get_init(handle, SENSOR_CONFIG_SET,
166 SCMI_PROTOCOL_SENSOR, sizeof(*cfg), 0, &t);
167 if (ret)
168 return ret;
169
170 cfg = t->tx.buf;
171 cfg->id = cpu_to_le32(sensor_id);
172 cfg->event_control = cpu_to_le32(evt_cntl);
173
174 ret = scmi_do_xfer(handle, t);
175
176 scmi_xfer_put(handle, t);
177 return ret;
178 }
179
scmi_sensor_trip_point_set(const struct scmi_handle * handle,u32 sensor_id,u8 trip_id,u64 trip_value)180 static int scmi_sensor_trip_point_set(const struct scmi_handle *handle,
181 u32 sensor_id, u8 trip_id, u64 trip_value)
182 {
183 int ret;
184 u32 evt_cntl = SENSOR_TP_BOTH;
185 struct scmi_xfer *t;
186 struct scmi_msg_set_sensor_trip_point *trip;
187
188 ret = scmi_xfer_get_init(handle, SENSOR_TRIP_POINT_SET,
189 SCMI_PROTOCOL_SENSOR, sizeof(*trip), 0, &t);
190 if (ret)
191 return ret;
192
193 trip = t->tx.buf;
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);
198
199 ret = scmi_do_xfer(handle, t);
200
201 scmi_xfer_put(handle, t);
202 return ret;
203 }
204
scmi_sensor_reading_get(const struct scmi_handle * handle,u32 sensor_id,bool async,u64 * value)205 static int scmi_sensor_reading_get(const struct scmi_handle *handle,
206 u32 sensor_id, bool async, u64 *value)
207 {
208 int ret;
209 struct scmi_xfer *t;
210 struct scmi_msg_sensor_reading_get *sensor;
211
212 ret = scmi_xfer_get_init(handle, SENSOR_READING_GET,
213 SCMI_PROTOCOL_SENSOR, sizeof(*sensor),
214 sizeof(u64), &t);
215 if (ret)
216 return ret;
217
218 sensor = t->tx.buf;
219 sensor->id = cpu_to_le32(sensor_id);
220 sensor->flags = cpu_to_le32(async ? SENSOR_READ_ASYNC : 0);
221
222 ret = scmi_do_xfer(handle, t);
223 if (!ret) {
224 __le32 *pval = t->rx.buf;
225
226 *value = le32_to_cpu(*pval);
227 *value |= (u64)le32_to_cpu(*(pval + 1)) << 32;
228 }
229
230 scmi_xfer_put(handle, t);
231 return ret;
232 }
233
234 static const struct scmi_sensor_info *
scmi_sensor_info_get(const struct scmi_handle * handle,u32 sensor_id)235 scmi_sensor_info_get(const struct scmi_handle *handle, u32 sensor_id)
236 {
237 struct sensors_info *si = handle->sensor_priv;
238
239 return si->sensors + sensor_id;
240 }
241
scmi_sensor_count_get(const struct scmi_handle * handle)242 static int scmi_sensor_count_get(const struct scmi_handle *handle)
243 {
244 struct sensors_info *si = handle->sensor_priv;
245
246 return si->num_sensors;
247 }
248
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,
255 };
256
scmi_sensors_protocol_init(struct scmi_handle * handle)257 static int scmi_sensors_protocol_init(struct scmi_handle *handle)
258 {
259 u32 version;
260 struct sensors_info *sinfo;
261
262 scmi_version_get(handle, SCMI_PROTOCOL_SENSOR, &version);
263
264 dev_dbg(handle->dev, "Sensor Version %d.%d\n",
265 PROTOCOL_REV_MAJOR(version), PROTOCOL_REV_MINOR(version));
266
267 sinfo = devm_kzalloc(handle->dev, sizeof(*sinfo), GFP_KERNEL);
268 if (!sinfo)
269 return -ENOMEM;
270
271 scmi_sensor_attributes_get(handle, sinfo);
272
273 sinfo->sensors = devm_kcalloc(handle->dev, sinfo->num_sensors,
274 sizeof(*sinfo->sensors), GFP_KERNEL);
275 if (!sinfo->sensors)
276 return -ENOMEM;
277
278 scmi_sensor_description_get(handle, sinfo);
279
280 handle->sensor_ops = &sensor_ops;
281 handle->sensor_priv = sinfo;
282
283 return 0;
284 }
285
scmi_sensors_init(void)286 static int __init scmi_sensors_init(void)
287 {
288 return scmi_protocol_register(SCMI_PROTOCOL_SENSOR,
289 &scmi_sensors_protocol_init);
290 }
291 subsys_initcall(scmi_sensors_init);
292