proc: test /proc/thread-self symlink
[linux/fpc-iii.git] / drivers / firmware / arm_scmi / sensors.c
blob27f2092b9882aef307763e214eb74c69f4db2af5
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3 * System Control and Management Interface (SCMI) Sensor Protocol
5 * Copyright (C) 2018 ARM Ltd.
6 */
8 #include "common.h"
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 {
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;
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];
43 struct scmi_msg_set_sensor_config {
44 __le32 id;
45 __le32 event_control;
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;
61 struct scmi_msg_sensor_reading_get {
62 __le32 id;
63 __le32 flags;
64 #define SENSOR_READ_ASYNC BIT(0)
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;
75 static int scmi_sensor_attributes_get(const struct scmi_handle *handle,
76 struct sensors_info *si)
78 int ret;
79 struct scmi_xfer *t;
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);
84 if (ret)
85 return ret;
87 attr = t->rx.buf;
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);
98 scmi_xfer_put(handle, t);
99 return ret;
102 static int scmi_sensor_description_get(const struct scmi_handle *handle,
103 struct sensors_info *si)
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;
111 ret = scmi_xfer_get_init(handle, SENSOR_DESCRIPTION_GET,
112 SCMI_PROTOCOL_SENSOR, sizeof(__le32), 0, &t);
113 if (ret)
114 return ret;
116 buf = t->rx.buf;
118 do {
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);
123 if (ret)
124 break;
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",
131 si->num_sensors);
132 break;
135 for (cnt = 0; cnt < num_returned; cnt++) {
136 u32 attrh;
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);
154 return ret;
157 static int
158 scmi_sensor_configuration_set(const struct scmi_handle *handle, u32 sensor_id)
160 int ret;
161 u32 evt_cntl = BIT(0);
162 struct scmi_xfer *t;
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);
167 if (ret)
168 return ret;
170 cfg = t->tx.buf;
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);
177 return ret;
180 static int scmi_sensor_trip_point_set(const struct scmi_handle *handle,
181 u32 sensor_id, u8 trip_id, u64 trip_value)
183 int ret;
184 u32 evt_cntl = SENSOR_TP_BOTH;
185 struct scmi_xfer *t;
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);
190 if (ret)
191 return ret;
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);
199 ret = scmi_do_xfer(handle, t);
201 scmi_xfer_put(handle, t);
202 return ret;
205 static int scmi_sensor_reading_get(const struct scmi_handle *handle,
206 u32 sensor_id, bool async, u64 *value)
208 int ret;
209 struct scmi_xfer *t;
210 struct scmi_msg_sensor_reading_get *sensor;
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;
218 sensor = t->tx.buf;
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);
223 if (!ret) {
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);
231 return ret;
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)
259 u32 version;
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);
268 if (!sinfo)
269 return -ENOMEM;
271 scmi_sensor_attributes_get(handle, sinfo);
273 sinfo->sensors = devm_kcalloc(handle->dev, sinfo->num_sensors,
274 sizeof(*sinfo->sensors), GFP_KERNEL);
275 if (!sinfo->sensors)
276 return -ENOMEM;
278 scmi_sensor_description_get(handle, sinfo);
280 handle->sensor_ops = &sensor_ops;
281 handle->sensor_priv = sinfo;
283 return 0;
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);