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