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