GNU Linux-libre 4.19.286-gnu1
[releases.git] / drivers / firmware / arm_scmi / sensors.c
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) & 0xff)
34                 __le32 attributes_high;
35 #define SENSOR_TYPE(x)          ((x) & 0xff)
36 #define SENSOR_SCALE(x)         (((x) >> 11) & 0x1f)
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
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
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                         strlcpy(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
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
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
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 *
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
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
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
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);