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 #define pr_fmt(fmt) "SCMI Notifications SENSOR - " fmt 9 10 #include <linux/scmi_protocol.h> 11 12 #include "common.h" 13 #include "notify.h" 14 15 enum scmi_sensor_protocol_cmd { 16 SENSOR_DESCRIPTION_GET = 0x3, 17 SENSOR_TRIP_POINT_NOTIFY = 0x4, 18 SENSOR_TRIP_POINT_CONFIG = 0x5, 19 SENSOR_READING_GET = 0x6, 20 }; 21 22 struct scmi_msg_resp_sensor_attributes { 23 __le16 num_sensors; 24 u8 max_requests; 25 u8 reserved; 26 __le32 reg_addr_low; 27 __le32 reg_addr_high; 28 __le32 reg_size; 29 }; 30 31 struct scmi_msg_resp_sensor_description { 32 __le16 num_returned; 33 __le16 num_remaining; 34 struct { 35 __le32 id; 36 __le32 attributes_low; 37 #define SUPPORTS_ASYNC_READ(x) ((x) & BIT(31)) 38 #define NUM_TRIP_POINTS(x) ((x) & 0xff) 39 __le32 attributes_high; 40 #define SENSOR_TYPE(x) ((x) & 0xff) 41 #define SENSOR_SCALE(x) (((x) >> 11) & 0x1f) 42 #define SENSOR_SCALE_SIGN BIT(4) 43 #define SENSOR_SCALE_EXTEND GENMASK(7, 5) 44 #define SENSOR_UPDATE_SCALE(x) (((x) >> 22) & 0x1f) 45 #define SENSOR_UPDATE_BASE(x) (((x) >> 27) & 0x1f) 46 u8 name[SCMI_MAX_STR_SIZE]; 47 } desc[0]; 48 }; 49 50 struct scmi_msg_sensor_trip_point_notify { 51 __le32 id; 52 __le32 event_control; 53 #define SENSOR_TP_NOTIFY_ALL BIT(0) 54 }; 55 56 struct scmi_msg_set_sensor_trip_point { 57 __le32 id; 58 __le32 event_control; 59 #define SENSOR_TP_EVENT_MASK (0x3) 60 #define SENSOR_TP_DISABLED 0x0 61 #define SENSOR_TP_POSITIVE 0x1 62 #define SENSOR_TP_NEGATIVE 0x2 63 #define SENSOR_TP_BOTH 0x3 64 #define SENSOR_TP_ID(x) (((x) & 0xff) << 4) 65 __le32 value_low; 66 __le32 value_high; 67 }; 68 69 struct scmi_msg_sensor_reading_get { 70 __le32 id; 71 __le32 flags; 72 #define SENSOR_READ_ASYNC BIT(0) 73 }; 74 75 struct scmi_sensor_trip_notify_payld { 76 __le32 agent_id; 77 __le32 sensor_id; 78 __le32 trip_point_desc; 79 }; 80 81 struct sensors_info { 82 u32 version; 83 int num_sensors; 84 int max_requests; 85 u64 reg_addr; 86 u32 reg_size; 87 struct scmi_sensor_info *sensors; 88 }; 89 90 static int scmi_sensor_attributes_get(const struct scmi_handle *handle, 91 struct sensors_info *si) 92 { 93 int ret; 94 struct scmi_xfer *t; 95 struct scmi_msg_resp_sensor_attributes *attr; 96 97 ret = scmi_xfer_get_init(handle, PROTOCOL_ATTRIBUTES, 98 SCMI_PROTOCOL_SENSOR, 0, sizeof(*attr), &t); 99 if (ret) 100 return ret; 101 102 attr = t->rx.buf; 103 104 ret = scmi_do_xfer(handle, t); 105 if (!ret) { 106 si->num_sensors = le16_to_cpu(attr->num_sensors); 107 si->max_requests = attr->max_requests; 108 si->reg_addr = le32_to_cpu(attr->reg_addr_low) | 109 (u64)le32_to_cpu(attr->reg_addr_high) << 32; 110 si->reg_size = le32_to_cpu(attr->reg_size); 111 } 112 113 scmi_xfer_put(handle, t); 114 return ret; 115 } 116 117 static int scmi_sensor_description_get(const struct scmi_handle *handle, 118 struct sensors_info *si) 119 { 120 int ret, cnt; 121 u32 desc_index = 0; 122 u16 num_returned, num_remaining; 123 struct scmi_xfer *t; 124 struct scmi_msg_resp_sensor_description *buf; 125 126 ret = scmi_xfer_get_init(handle, SENSOR_DESCRIPTION_GET, 127 SCMI_PROTOCOL_SENSOR, sizeof(__le32), 0, &t); 128 if (ret) 129 return ret; 130 131 buf = t->rx.buf; 132 133 do { 134 /* Set the number of sensors to be skipped/already read */ 135 put_unaligned_le32(desc_index, t->tx.buf); 136 137 ret = scmi_do_xfer(handle, t); 138 if (ret) 139 break; 140 141 num_returned = le16_to_cpu(buf->num_returned); 142 num_remaining = le16_to_cpu(buf->num_remaining); 143 144 if (desc_index + num_returned > si->num_sensors) { 145 dev_err(handle->dev, "No. of sensors can't exceed %d", 146 si->num_sensors); 147 break; 148 } 149 150 for (cnt = 0; cnt < num_returned; cnt++) { 151 u32 attrh, attrl; 152 struct scmi_sensor_info *s; 153 154 attrl = le32_to_cpu(buf->desc[cnt].attributes_low); 155 attrh = le32_to_cpu(buf->desc[cnt].attributes_high); 156 s = &si->sensors[desc_index + cnt]; 157 s->id = le32_to_cpu(buf->desc[cnt].id); 158 s->type = SENSOR_TYPE(attrh); 159 s->scale = SENSOR_SCALE(attrh); 160 /* Sign extend to a full s8 */ 161 if (s->scale & SENSOR_SCALE_SIGN) 162 s->scale |= SENSOR_SCALE_EXTEND; 163 s->async = SUPPORTS_ASYNC_READ(attrl); 164 s->num_trip_points = NUM_TRIP_POINTS(attrl); 165 strlcpy(s->name, buf->desc[cnt].name, SCMI_MAX_STR_SIZE); 166 } 167 168 desc_index += num_returned; 169 /* 170 * check for both returned and remaining to avoid infinite 171 * loop due to buggy firmware 172 */ 173 } while (num_returned && num_remaining); 174 175 scmi_xfer_put(handle, t); 176 return ret; 177 } 178 179 static int scmi_sensor_trip_point_notify(const struct scmi_handle *handle, 180 u32 sensor_id, bool enable) 181 { 182 int ret; 183 u32 evt_cntl = enable ? SENSOR_TP_NOTIFY_ALL : 0; 184 struct scmi_xfer *t; 185 struct scmi_msg_sensor_trip_point_notify *cfg; 186 187 ret = scmi_xfer_get_init(handle, SENSOR_TRIP_POINT_NOTIFY, 188 SCMI_PROTOCOL_SENSOR, sizeof(*cfg), 0, &t); 189 if (ret) 190 return ret; 191 192 cfg = t->tx.buf; 193 cfg->id = cpu_to_le32(sensor_id); 194 cfg->event_control = cpu_to_le32(evt_cntl); 195 196 ret = scmi_do_xfer(handle, t); 197 198 scmi_xfer_put(handle, t); 199 return ret; 200 } 201 202 static int 203 scmi_sensor_trip_point_config(const struct scmi_handle *handle, u32 sensor_id, 204 u8 trip_id, u64 trip_value) 205 { 206 int ret; 207 u32 evt_cntl = SENSOR_TP_BOTH; 208 struct scmi_xfer *t; 209 struct scmi_msg_set_sensor_trip_point *trip; 210 211 ret = scmi_xfer_get_init(handle, SENSOR_TRIP_POINT_CONFIG, 212 SCMI_PROTOCOL_SENSOR, sizeof(*trip), 0, &t); 213 if (ret) 214 return ret; 215 216 trip = t->tx.buf; 217 trip->id = cpu_to_le32(sensor_id); 218 trip->event_control = cpu_to_le32(evt_cntl | SENSOR_TP_ID(trip_id)); 219 trip->value_low = cpu_to_le32(trip_value & 0xffffffff); 220 trip->value_high = cpu_to_le32(trip_value >> 32); 221 222 ret = scmi_do_xfer(handle, t); 223 224 scmi_xfer_put(handle, t); 225 return ret; 226 } 227 228 static int scmi_sensor_reading_get(const struct scmi_handle *handle, 229 u32 sensor_id, u64 *value) 230 { 231 int ret; 232 struct scmi_xfer *t; 233 struct scmi_msg_sensor_reading_get *sensor; 234 struct sensors_info *si = handle->sensor_priv; 235 struct scmi_sensor_info *s = si->sensors + sensor_id; 236 237 ret = scmi_xfer_get_init(handle, SENSOR_READING_GET, 238 SCMI_PROTOCOL_SENSOR, sizeof(*sensor), 239 sizeof(u64), &t); 240 if (ret) 241 return ret; 242 243 sensor = t->tx.buf; 244 sensor->id = cpu_to_le32(sensor_id); 245 246 if (s->async) { 247 sensor->flags = cpu_to_le32(SENSOR_READ_ASYNC); 248 ret = scmi_do_xfer_with_response(handle, t); 249 if (!ret) 250 *value = get_unaligned_le64((void *) 251 ((__le32 *)t->rx.buf + 1)); 252 } else { 253 sensor->flags = cpu_to_le32(0); 254 ret = scmi_do_xfer(handle, t); 255 if (!ret) 256 *value = get_unaligned_le64(t->rx.buf); 257 } 258 259 scmi_xfer_put(handle, t); 260 return ret; 261 } 262 263 static const struct scmi_sensor_info * 264 scmi_sensor_info_get(const struct scmi_handle *handle, u32 sensor_id) 265 { 266 struct sensors_info *si = handle->sensor_priv; 267 268 return si->sensors + sensor_id; 269 } 270 271 static int scmi_sensor_count_get(const struct scmi_handle *handle) 272 { 273 struct sensors_info *si = handle->sensor_priv; 274 275 return si->num_sensors; 276 } 277 278 static struct scmi_sensor_ops sensor_ops = { 279 .count_get = scmi_sensor_count_get, 280 .info_get = scmi_sensor_info_get, 281 .trip_point_config = scmi_sensor_trip_point_config, 282 .reading_get = scmi_sensor_reading_get, 283 }; 284 285 static int scmi_sensor_set_notify_enabled(const struct scmi_handle *handle, 286 u8 evt_id, u32 src_id, bool enable) 287 { 288 int ret; 289 290 ret = scmi_sensor_trip_point_notify(handle, src_id, enable); 291 if (ret) 292 pr_debug("FAIL_ENABLED - evt[%X] dom[%d] - ret:%d\n", 293 evt_id, src_id, ret); 294 295 return ret; 296 } 297 298 static void *scmi_sensor_fill_custom_report(const struct scmi_handle *handle, 299 u8 evt_id, ktime_t timestamp, 300 const void *payld, size_t payld_sz, 301 void *report, u32 *src_id) 302 { 303 const struct scmi_sensor_trip_notify_payld *p = payld; 304 struct scmi_sensor_trip_point_report *r = report; 305 306 if (evt_id != SCMI_EVENT_SENSOR_TRIP_POINT_EVENT || 307 sizeof(*p) != payld_sz) 308 return NULL; 309 310 r->timestamp = timestamp; 311 r->agent_id = le32_to_cpu(p->agent_id); 312 r->sensor_id = le32_to_cpu(p->sensor_id); 313 r->trip_point_desc = le32_to_cpu(p->trip_point_desc); 314 *src_id = r->sensor_id; 315 316 return r; 317 } 318 319 static const struct scmi_event sensor_events[] = { 320 { 321 .id = SCMI_EVENT_SENSOR_TRIP_POINT_EVENT, 322 .max_payld_sz = sizeof(struct scmi_sensor_trip_notify_payld), 323 .max_report_sz = sizeof(struct scmi_sensor_trip_point_report), 324 }, 325 }; 326 327 static const struct scmi_event_ops sensor_event_ops = { 328 .set_notify_enabled = scmi_sensor_set_notify_enabled, 329 .fill_custom_report = scmi_sensor_fill_custom_report, 330 }; 331 332 static int scmi_sensors_protocol_init(struct scmi_handle *handle) 333 { 334 u32 version; 335 struct sensors_info *sinfo; 336 337 scmi_version_get(handle, SCMI_PROTOCOL_SENSOR, &version); 338 339 dev_dbg(handle->dev, "Sensor Version %d.%d\n", 340 PROTOCOL_REV_MAJOR(version), PROTOCOL_REV_MINOR(version)); 341 342 sinfo = devm_kzalloc(handle->dev, sizeof(*sinfo), GFP_KERNEL); 343 if (!sinfo) 344 return -ENOMEM; 345 346 scmi_sensor_attributes_get(handle, sinfo); 347 348 sinfo->sensors = devm_kcalloc(handle->dev, sinfo->num_sensors, 349 sizeof(*sinfo->sensors), GFP_KERNEL); 350 if (!sinfo->sensors) 351 return -ENOMEM; 352 353 scmi_sensor_description_get(handle, sinfo); 354 355 scmi_register_protocol_events(handle, 356 SCMI_PROTOCOL_SENSOR, SCMI_PROTO_QUEUE_SZ, 357 &sensor_event_ops, sensor_events, 358 ARRAY_SIZE(sensor_events), 359 sinfo->num_sensors); 360 361 sinfo->version = version; 362 handle->sensor_ops = &sensor_ops; 363 handle->sensor_priv = sinfo; 364 365 return 0; 366 } 367 368 static int __init scmi_sensors_init(void) 369 { 370 return scmi_protocol_register(SCMI_PROTOCOL_SENSOR, 371 &scmi_sensors_protocol_init); 372 } 373 subsys_initcall(scmi_sensors_init); 374