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_SCALE_SIGN	BIT(4)
38 #define SENSOR_SCALE_EXTEND	GENMASK(7, 5)
39 #define SENSOR_UPDATE_SCALE(x)	(((x) >> 22) & 0x1f)
40 #define SENSOR_UPDATE_BASE(x)	(((x) >> 27) & 0x1f)
41 		    u8 name[SCMI_MAX_STR_SIZE];
42 	} desc[0];
43 };
44 
45 struct scmi_msg_set_sensor_config {
46 	__le32 id;
47 	__le32 event_control;
48 };
49 
50 struct scmi_msg_set_sensor_trip_point {
51 	__le32 id;
52 	__le32 event_control;
53 #define SENSOR_TP_EVENT_MASK	(0x3)
54 #define SENSOR_TP_DISABLED	0x0
55 #define SENSOR_TP_POSITIVE	0x1
56 #define SENSOR_TP_NEGATIVE	0x2
57 #define SENSOR_TP_BOTH		0x3
58 #define SENSOR_TP_ID(x)		(((x) & 0xff) << 4)
59 	__le32 value_low;
60 	__le32 value_high;
61 };
62 
63 struct scmi_msg_sensor_reading_get {
64 	__le32 id;
65 	__le32 flags;
66 #define SENSOR_READ_ASYNC	BIT(0)
67 };
68 
69 struct sensors_info {
70 	int num_sensors;
71 	int max_requests;
72 	u64 reg_addr;
73 	u32 reg_size;
74 	struct scmi_sensor_info *sensors;
75 };
76 
77 static int scmi_sensor_attributes_get(const struct scmi_handle *handle,
78 				      struct sensors_info *si)
79 {
80 	int ret;
81 	struct scmi_xfer *t;
82 	struct scmi_msg_resp_sensor_attributes *attr;
83 
84 	ret = scmi_xfer_get_init(handle, PROTOCOL_ATTRIBUTES,
85 				 SCMI_PROTOCOL_SENSOR, 0, sizeof(*attr), &t);
86 	if (ret)
87 		return ret;
88 
89 	attr = t->rx.buf;
90 
91 	ret = scmi_do_xfer(handle, t);
92 	if (!ret) {
93 		si->num_sensors = le16_to_cpu(attr->num_sensors);
94 		si->max_requests = attr->max_requests;
95 		si->reg_addr = le32_to_cpu(attr->reg_addr_low) |
96 				(u64)le32_to_cpu(attr->reg_addr_high) << 32;
97 		si->reg_size = le32_to_cpu(attr->reg_size);
98 	}
99 
100 	scmi_xfer_put(handle, t);
101 	return ret;
102 }
103 
104 static int scmi_sensor_description_get(const struct scmi_handle *handle,
105 				       struct sensors_info *si)
106 {
107 	int ret, cnt;
108 	u32 desc_index = 0;
109 	u16 num_returned, num_remaining;
110 	struct scmi_xfer *t;
111 	struct scmi_msg_resp_sensor_description *buf;
112 
113 	ret = scmi_xfer_get_init(handle, SENSOR_DESCRIPTION_GET,
114 				 SCMI_PROTOCOL_SENSOR, sizeof(__le32), 0, &t);
115 	if (ret)
116 		return ret;
117 
118 	buf = t->rx.buf;
119 
120 	do {
121 		/* Set the number of sensors to be skipped/already read */
122 		*(__le32 *)t->tx.buf = cpu_to_le32(desc_index);
123 
124 		ret = scmi_do_xfer(handle, t);
125 		if (ret)
126 			break;
127 
128 		num_returned = le16_to_cpu(buf->num_returned);
129 		num_remaining = le16_to_cpu(buf->num_remaining);
130 
131 		if (desc_index + num_returned > si->num_sensors) {
132 			dev_err(handle->dev, "No. of sensors can't exceed %d",
133 				si->num_sensors);
134 			break;
135 		}
136 
137 		for (cnt = 0; cnt < num_returned; cnt++) {
138 			u32 attrh;
139 			struct scmi_sensor_info *s;
140 
141 			attrh = le32_to_cpu(buf->desc[cnt].attributes_high);
142 			s = &si->sensors[desc_index + cnt];
143 			s->id = le32_to_cpu(buf->desc[cnt].id);
144 			s->type = SENSOR_TYPE(attrh);
145 			s->scale = SENSOR_SCALE(attrh);
146 			/* Sign extend to a full s8 */
147 			if (s->scale & SENSOR_SCALE_SIGN)
148 				s->scale |= SENSOR_SCALE_EXTEND;
149 			strlcpy(s->name, buf->desc[cnt].name, SCMI_MAX_STR_SIZE);
150 		}
151 
152 		desc_index += num_returned;
153 		/*
154 		 * check for both returned and remaining to avoid infinite
155 		 * loop due to buggy firmware
156 		 */
157 	} while (num_returned && num_remaining);
158 
159 	scmi_xfer_put(handle, t);
160 	return ret;
161 }
162 
163 static int
164 scmi_sensor_configuration_set(const struct scmi_handle *handle, u32 sensor_id)
165 {
166 	int ret;
167 	u32 evt_cntl = BIT(0);
168 	struct scmi_xfer *t;
169 	struct scmi_msg_set_sensor_config *cfg;
170 
171 	ret = scmi_xfer_get_init(handle, SENSOR_CONFIG_SET,
172 				 SCMI_PROTOCOL_SENSOR, sizeof(*cfg), 0, &t);
173 	if (ret)
174 		return ret;
175 
176 	cfg = t->tx.buf;
177 	cfg->id = cpu_to_le32(sensor_id);
178 	cfg->event_control = cpu_to_le32(evt_cntl);
179 
180 	ret = scmi_do_xfer(handle, t);
181 
182 	scmi_xfer_put(handle, t);
183 	return ret;
184 }
185 
186 static int scmi_sensor_trip_point_set(const struct scmi_handle *handle,
187 				      u32 sensor_id, u8 trip_id, u64 trip_value)
188 {
189 	int ret;
190 	u32 evt_cntl = SENSOR_TP_BOTH;
191 	struct scmi_xfer *t;
192 	struct scmi_msg_set_sensor_trip_point *trip;
193 
194 	ret = scmi_xfer_get_init(handle, SENSOR_TRIP_POINT_SET,
195 				 SCMI_PROTOCOL_SENSOR, sizeof(*trip), 0, &t);
196 	if (ret)
197 		return ret;
198 
199 	trip = t->tx.buf;
200 	trip->id = cpu_to_le32(sensor_id);
201 	trip->event_control = cpu_to_le32(evt_cntl | SENSOR_TP_ID(trip_id));
202 	trip->value_low = cpu_to_le32(trip_value & 0xffffffff);
203 	trip->value_high = cpu_to_le32(trip_value >> 32);
204 
205 	ret = scmi_do_xfer(handle, t);
206 
207 	scmi_xfer_put(handle, t);
208 	return ret;
209 }
210 
211 static int scmi_sensor_reading_get(const struct scmi_handle *handle,
212 				   u32 sensor_id, bool async, u64 *value)
213 {
214 	int ret;
215 	struct scmi_xfer *t;
216 	struct scmi_msg_sensor_reading_get *sensor;
217 
218 	ret = scmi_xfer_get_init(handle, SENSOR_READING_GET,
219 				 SCMI_PROTOCOL_SENSOR, sizeof(*sensor),
220 				 sizeof(u64), &t);
221 	if (ret)
222 		return ret;
223 
224 	sensor = t->tx.buf;
225 	sensor->id = cpu_to_le32(sensor_id);
226 	sensor->flags = cpu_to_le32(async ? SENSOR_READ_ASYNC : 0);
227 
228 	ret = scmi_do_xfer(handle, t);
229 	if (!ret) {
230 		__le32 *pval = t->rx.buf;
231 
232 		*value = le32_to_cpu(*pval);
233 		*value |= (u64)le32_to_cpu(*(pval + 1)) << 32;
234 	}
235 
236 	scmi_xfer_put(handle, t);
237 	return ret;
238 }
239 
240 static const struct scmi_sensor_info *
241 scmi_sensor_info_get(const struct scmi_handle *handle, u32 sensor_id)
242 {
243 	struct sensors_info *si = handle->sensor_priv;
244 
245 	return si->sensors + sensor_id;
246 }
247 
248 static int scmi_sensor_count_get(const struct scmi_handle *handle)
249 {
250 	struct sensors_info *si = handle->sensor_priv;
251 
252 	return si->num_sensors;
253 }
254 
255 static struct scmi_sensor_ops sensor_ops = {
256 	.count_get = scmi_sensor_count_get,
257 	.info_get = scmi_sensor_info_get,
258 	.configuration_set = scmi_sensor_configuration_set,
259 	.trip_point_set = scmi_sensor_trip_point_set,
260 	.reading_get = scmi_sensor_reading_get,
261 };
262 
263 static int scmi_sensors_protocol_init(struct scmi_handle *handle)
264 {
265 	u32 version;
266 	struct sensors_info *sinfo;
267 
268 	scmi_version_get(handle, SCMI_PROTOCOL_SENSOR, &version);
269 
270 	dev_dbg(handle->dev, "Sensor Version %d.%d\n",
271 		PROTOCOL_REV_MAJOR(version), PROTOCOL_REV_MINOR(version));
272 
273 	sinfo = devm_kzalloc(handle->dev, sizeof(*sinfo), GFP_KERNEL);
274 	if (!sinfo)
275 		return -ENOMEM;
276 
277 	scmi_sensor_attributes_get(handle, sinfo);
278 
279 	sinfo->sensors = devm_kcalloc(handle->dev, sinfo->num_sensors,
280 				      sizeof(*sinfo->sensors), GFP_KERNEL);
281 	if (!sinfo->sensors)
282 		return -ENOMEM;
283 
284 	scmi_sensor_description_get(handle, sinfo);
285 
286 	handle->sensor_ops = &sensor_ops;
287 	handle->sensor_priv = sinfo;
288 
289 	return 0;
290 }
291 
292 static int __init scmi_sensors_init(void)
293 {
294 	return scmi_protocol_register(SCMI_PROTOCOL_SENSOR,
295 				      &scmi_sensors_protocol_init);
296 }
297 subsys_initcall(scmi_sensors_init);
298