1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * System Control and Management Interface (SCMI) Base Protocol 4 * 5 * Copyright (C) 2018-2021 ARM Ltd. 6 */ 7 8 #define pr_fmt(fmt) "SCMI Notifications BASE - " fmt 9 10 #include <linux/module.h> 11 #include <linux/scmi_protocol.h> 12 13 #include "common.h" 14 #include "notify.h" 15 16 #define SCMI_BASE_NUM_SOURCES 1 17 #define SCMI_BASE_MAX_CMD_ERR_COUNT 1024 18 19 enum scmi_base_protocol_cmd { 20 BASE_DISCOVER_VENDOR = 0x3, 21 BASE_DISCOVER_SUB_VENDOR = 0x4, 22 BASE_DISCOVER_IMPLEMENT_VERSION = 0x5, 23 BASE_DISCOVER_LIST_PROTOCOLS = 0x6, 24 BASE_DISCOVER_AGENT = 0x7, 25 BASE_NOTIFY_ERRORS = 0x8, 26 BASE_SET_DEVICE_PERMISSIONS = 0x9, 27 BASE_SET_PROTOCOL_PERMISSIONS = 0xa, 28 BASE_RESET_AGENT_CONFIGURATION = 0xb, 29 }; 30 31 struct scmi_msg_resp_base_attributes { 32 u8 num_protocols; 33 u8 num_agents; 34 __le16 reserved; 35 }; 36 37 struct scmi_msg_resp_base_discover_agent { 38 __le32 agent_id; 39 u8 name[SCMI_MAX_STR_SIZE]; 40 }; 41 42 43 struct scmi_msg_base_error_notify { 44 __le32 event_control; 45 #define BASE_TP_NOTIFY_ALL BIT(0) 46 }; 47 48 struct scmi_base_error_notify_payld { 49 __le32 agent_id; 50 __le32 error_status; 51 #define IS_FATAL_ERROR(x) ((x) & BIT(31)) 52 #define ERROR_CMD_COUNT(x) FIELD_GET(GENMASK(9, 0), (x)) 53 __le64 msg_reports[SCMI_BASE_MAX_CMD_ERR_COUNT]; 54 }; 55 56 /** 57 * scmi_base_attributes_get() - gets the implementation details 58 * that are associated with the base protocol. 59 * 60 * @ph: SCMI protocol handle 61 * 62 * Return: 0 on success, else appropriate SCMI error. 63 */ 64 static int scmi_base_attributes_get(const struct scmi_protocol_handle *ph) 65 { 66 int ret; 67 struct scmi_xfer *t; 68 struct scmi_msg_resp_base_attributes *attr_info; 69 struct scmi_revision_info *rev = ph->get_priv(ph); 70 71 ret = ph->xops->xfer_get_init(ph, PROTOCOL_ATTRIBUTES, 72 0, sizeof(*attr_info), &t); 73 if (ret) 74 return ret; 75 76 ret = ph->xops->do_xfer(ph, t); 77 if (!ret) { 78 attr_info = t->rx.buf; 79 rev->num_protocols = attr_info->num_protocols; 80 rev->num_agents = attr_info->num_agents; 81 } 82 83 ph->xops->xfer_put(ph, t); 84 85 return ret; 86 } 87 88 /** 89 * scmi_base_vendor_id_get() - gets vendor/subvendor identifier ASCII string. 90 * 91 * @ph: SCMI protocol handle 92 * @sub_vendor: specify true if sub-vendor ID is needed 93 * 94 * Return: 0 on success, else appropriate SCMI error. 95 */ 96 static int 97 scmi_base_vendor_id_get(const struct scmi_protocol_handle *ph, bool sub_vendor) 98 { 99 u8 cmd; 100 int ret, size; 101 char *vendor_id; 102 struct scmi_xfer *t; 103 struct scmi_revision_info *rev = ph->get_priv(ph); 104 105 106 if (sub_vendor) { 107 cmd = BASE_DISCOVER_SUB_VENDOR; 108 vendor_id = rev->sub_vendor_id; 109 size = ARRAY_SIZE(rev->sub_vendor_id); 110 } else { 111 cmd = BASE_DISCOVER_VENDOR; 112 vendor_id = rev->vendor_id; 113 size = ARRAY_SIZE(rev->vendor_id); 114 } 115 116 ret = ph->xops->xfer_get_init(ph, cmd, 0, size, &t); 117 if (ret) 118 return ret; 119 120 ret = ph->xops->do_xfer(ph, t); 121 if (!ret) 122 memcpy(vendor_id, t->rx.buf, size); 123 124 ph->xops->xfer_put(ph, t); 125 126 return ret; 127 } 128 129 /** 130 * scmi_base_implementation_version_get() - gets a vendor-specific 131 * implementation 32-bit version. The format of the version number is 132 * vendor-specific 133 * 134 * @ph: SCMI protocol handle 135 * 136 * Return: 0 on success, else appropriate SCMI error. 137 */ 138 static int 139 scmi_base_implementation_version_get(const struct scmi_protocol_handle *ph) 140 { 141 int ret; 142 __le32 *impl_ver; 143 struct scmi_xfer *t; 144 struct scmi_revision_info *rev = ph->get_priv(ph); 145 146 ret = ph->xops->xfer_get_init(ph, BASE_DISCOVER_IMPLEMENT_VERSION, 147 0, sizeof(*impl_ver), &t); 148 if (ret) 149 return ret; 150 151 ret = ph->xops->do_xfer(ph, t); 152 if (!ret) { 153 impl_ver = t->rx.buf; 154 rev->impl_ver = le32_to_cpu(*impl_ver); 155 } 156 157 ph->xops->xfer_put(ph, t); 158 159 return ret; 160 } 161 162 /** 163 * scmi_base_implementation_list_get() - gets the list of protocols it is 164 * OSPM is allowed to access 165 * 166 * @ph: SCMI protocol handle 167 * @protocols_imp: pointer to hold the list of protocol identifiers 168 * 169 * Return: 0 on success, else appropriate SCMI error. 170 */ 171 static int 172 scmi_base_implementation_list_get(const struct scmi_protocol_handle *ph, 173 u8 *protocols_imp) 174 { 175 u8 *list; 176 int ret, loop; 177 struct scmi_xfer *t; 178 __le32 *num_skip, *num_ret; 179 u32 tot_num_ret = 0, loop_num_ret; 180 struct device *dev = ph->dev; 181 struct scmi_revision_info *rev = ph->get_priv(ph); 182 183 ret = ph->xops->xfer_get_init(ph, BASE_DISCOVER_LIST_PROTOCOLS, 184 sizeof(*num_skip), 0, &t); 185 if (ret) 186 return ret; 187 188 num_skip = t->tx.buf; 189 num_ret = t->rx.buf; 190 list = t->rx.buf + sizeof(*num_ret); 191 192 do { 193 size_t real_list_sz; 194 u32 calc_list_sz; 195 196 /* Set the number of protocols to be skipped/already read */ 197 *num_skip = cpu_to_le32(tot_num_ret); 198 199 ret = ph->xops->do_xfer(ph, t); 200 if (ret) 201 break; 202 203 loop_num_ret = le32_to_cpu(*num_ret); 204 if (!loop_num_ret) 205 break; 206 207 if (loop_num_ret > rev->num_protocols - tot_num_ret) { 208 dev_err(dev, 209 "No. Returned protocols > Total protocols.\n"); 210 break; 211 } 212 213 if (t->rx.len < (sizeof(u32) * 2)) { 214 dev_err(dev, "Truncated reply - rx.len:%zd\n", 215 t->rx.len); 216 ret = -EPROTO; 217 break; 218 } 219 220 real_list_sz = t->rx.len - sizeof(u32); 221 calc_list_sz = (1 + (loop_num_ret - 1) / sizeof(u32)) * 222 sizeof(u32); 223 if (calc_list_sz != real_list_sz) { 224 dev_err(dev, 225 "Malformed reply - real_sz:%zd calc_sz:%u\n", 226 real_list_sz, calc_list_sz); 227 ret = -EPROTO; 228 break; 229 } 230 231 for (loop = 0; loop < loop_num_ret; loop++) 232 protocols_imp[tot_num_ret + loop] = *(list + loop); 233 234 tot_num_ret += loop_num_ret; 235 236 ph->xops->reset_rx_to_maxsz(ph, t); 237 } while (tot_num_ret < rev->num_protocols); 238 239 ph->xops->xfer_put(ph, t); 240 241 return ret; 242 } 243 244 /** 245 * scmi_base_discover_agent_get() - discover the name of an agent 246 * 247 * @ph: SCMI protocol handle 248 * @id: Agent identifier 249 * @name: Agent identifier ASCII string 250 * 251 * An agent id of 0 is reserved to identify the platform itself. 252 * Generally operating system is represented as "OSPM" 253 * 254 * Return: 0 on success, else appropriate SCMI error. 255 */ 256 static int scmi_base_discover_agent_get(const struct scmi_protocol_handle *ph, 257 int id, char *name) 258 { 259 int ret; 260 struct scmi_msg_resp_base_discover_agent *agent_info; 261 struct scmi_xfer *t; 262 263 ret = ph->xops->xfer_get_init(ph, BASE_DISCOVER_AGENT, 264 sizeof(__le32), sizeof(*agent_info), &t); 265 if (ret) 266 return ret; 267 268 put_unaligned_le32(id, t->tx.buf); 269 270 ret = ph->xops->do_xfer(ph, t); 271 if (!ret) { 272 agent_info = t->rx.buf; 273 strlcpy(name, agent_info->name, SCMI_MAX_STR_SIZE); 274 } 275 276 ph->xops->xfer_put(ph, t); 277 278 return ret; 279 } 280 281 static int scmi_base_error_notify(const struct scmi_protocol_handle *ph, 282 bool enable) 283 { 284 int ret; 285 u32 evt_cntl = enable ? BASE_TP_NOTIFY_ALL : 0; 286 struct scmi_xfer *t; 287 struct scmi_msg_base_error_notify *cfg; 288 289 ret = ph->xops->xfer_get_init(ph, BASE_NOTIFY_ERRORS, 290 sizeof(*cfg), 0, &t); 291 if (ret) 292 return ret; 293 294 cfg = t->tx.buf; 295 cfg->event_control = cpu_to_le32(evt_cntl); 296 297 ret = ph->xops->do_xfer(ph, t); 298 299 ph->xops->xfer_put(ph, t); 300 return ret; 301 } 302 303 static int scmi_base_set_notify_enabled(const struct scmi_protocol_handle *ph, 304 u8 evt_id, u32 src_id, bool enable) 305 { 306 int ret; 307 308 ret = scmi_base_error_notify(ph, enable); 309 if (ret) 310 pr_debug("FAIL_ENABLED - evt[%X] ret:%d\n", evt_id, ret); 311 312 return ret; 313 } 314 315 static void *scmi_base_fill_custom_report(const struct scmi_protocol_handle *ph, 316 u8 evt_id, ktime_t timestamp, 317 const void *payld, size_t payld_sz, 318 void *report, u32 *src_id) 319 { 320 int i; 321 const struct scmi_base_error_notify_payld *p = payld; 322 struct scmi_base_error_report *r = report; 323 324 /* 325 * BaseError notification payload is variable in size but 326 * up to a maximum length determined by the struct ponted by p. 327 * Instead payld_sz is the effective length of this notification 328 * payload so cannot be greater of the maximum allowed size as 329 * pointed by p. 330 */ 331 if (evt_id != SCMI_EVENT_BASE_ERROR_EVENT || sizeof(*p) < payld_sz) 332 return NULL; 333 334 r->timestamp = timestamp; 335 r->agent_id = le32_to_cpu(p->agent_id); 336 r->fatal = IS_FATAL_ERROR(le32_to_cpu(p->error_status)); 337 r->cmd_count = ERROR_CMD_COUNT(le32_to_cpu(p->error_status)); 338 for (i = 0; i < r->cmd_count; i++) 339 r->reports[i] = le64_to_cpu(p->msg_reports[i]); 340 *src_id = 0; 341 342 return r; 343 } 344 345 static const struct scmi_event base_events[] = { 346 { 347 .id = SCMI_EVENT_BASE_ERROR_EVENT, 348 .max_payld_sz = sizeof(struct scmi_base_error_notify_payld), 349 .max_report_sz = sizeof(struct scmi_base_error_report) + 350 SCMI_BASE_MAX_CMD_ERR_COUNT * sizeof(u64), 351 }, 352 }; 353 354 static const struct scmi_event_ops base_event_ops = { 355 .set_notify_enabled = scmi_base_set_notify_enabled, 356 .fill_custom_report = scmi_base_fill_custom_report, 357 }; 358 359 static const struct scmi_protocol_events base_protocol_events = { 360 .queue_sz = 4 * SCMI_PROTO_QUEUE_SZ, 361 .ops = &base_event_ops, 362 .evts = base_events, 363 .num_events = ARRAY_SIZE(base_events), 364 .num_sources = SCMI_BASE_NUM_SOURCES, 365 }; 366 367 static int scmi_base_protocol_init(const struct scmi_protocol_handle *ph) 368 { 369 int id, ret; 370 u8 *prot_imp; 371 u32 version; 372 char name[SCMI_MAX_STR_SIZE]; 373 struct device *dev = ph->dev; 374 struct scmi_revision_info *rev = scmi_revision_area_get(ph); 375 376 ret = ph->xops->version_get(ph, &version); 377 if (ret) 378 return ret; 379 380 rev->major_ver = PROTOCOL_REV_MAJOR(version), 381 rev->minor_ver = PROTOCOL_REV_MINOR(version); 382 ph->set_priv(ph, rev); 383 384 ret = scmi_base_attributes_get(ph); 385 if (ret) 386 return ret; 387 388 prot_imp = devm_kcalloc(dev, rev->num_protocols, sizeof(u8), 389 GFP_KERNEL); 390 if (!prot_imp) 391 return -ENOMEM; 392 393 scmi_base_vendor_id_get(ph, false); 394 scmi_base_vendor_id_get(ph, true); 395 scmi_base_implementation_version_get(ph); 396 scmi_base_implementation_list_get(ph, prot_imp); 397 398 scmi_setup_protocol_implemented(ph, prot_imp); 399 400 dev_info(dev, "SCMI Protocol v%d.%d '%s:%s' Firmware version 0x%x\n", 401 rev->major_ver, rev->minor_ver, rev->vendor_id, 402 rev->sub_vendor_id, rev->impl_ver); 403 dev_dbg(dev, "Found %d protocol(s) %d agent(s)\n", rev->num_protocols, 404 rev->num_agents); 405 406 for (id = 0; id < rev->num_agents; id++) { 407 scmi_base_discover_agent_get(ph, id, name); 408 dev_dbg(dev, "Agent %d: %s\n", id, name); 409 } 410 411 return 0; 412 } 413 414 static const struct scmi_protocol scmi_base = { 415 .id = SCMI_PROTOCOL_BASE, 416 .owner = NULL, 417 .instance_init = &scmi_base_protocol_init, 418 .ops = NULL, 419 .events = &base_protocol_events, 420 }; 421 422 DEFINE_SCMI_PROTOCOL_REGISTER_UNREGISTER(base, scmi_base) 423