xref: /linux/drivers/firmware/arm_scmi/sensors.c (revision 856e7c4b619af622d56b3b454f7bec32a170ac99)
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 
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 			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
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);
292