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