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 182 ret = ph->xops->xfer_get_init(ph, BASE_DISCOVER_LIST_PROTOCOLS, 183 sizeof(*num_skip), 0, &t); 184 if (ret) 185 return ret; 186 187 num_skip = t->tx.buf; 188 num_ret = t->rx.buf; 189 list = t->rx.buf + sizeof(*num_ret); 190 191 do { 192 /* Set the number of protocols to be skipped/already read */ 193 *num_skip = cpu_to_le32(tot_num_ret); 194 195 ret = ph->xops->do_xfer(ph, t); 196 if (ret) 197 break; 198 199 loop_num_ret = le32_to_cpu(*num_ret); 200 if (tot_num_ret + loop_num_ret > MAX_PROTOCOLS_IMP) { 201 dev_err(dev, "No. of Protocol > MAX_PROTOCOLS_IMP"); 202 break; 203 } 204 205 for (loop = 0; loop < loop_num_ret; loop++) 206 protocols_imp[tot_num_ret + loop] = *(list + loop); 207 208 tot_num_ret += loop_num_ret; 209 210 ph->xops->reset_rx_to_maxsz(ph, t); 211 } while (loop_num_ret); 212 213 ph->xops->xfer_put(ph, t); 214 215 return ret; 216 } 217 218 /** 219 * scmi_base_discover_agent_get() - discover the name of an agent 220 * 221 * @ph: SCMI protocol handle 222 * @id: Agent identifier 223 * @name: Agent identifier ASCII string 224 * 225 * An agent id of 0 is reserved to identify the platform itself. 226 * Generally operating system is represented as "OSPM" 227 * 228 * Return: 0 on success, else appropriate SCMI error. 229 */ 230 static int scmi_base_discover_agent_get(const struct scmi_protocol_handle *ph, 231 int id, char *name) 232 { 233 int ret; 234 struct scmi_msg_resp_base_discover_agent *agent_info; 235 struct scmi_xfer *t; 236 237 ret = ph->xops->xfer_get_init(ph, BASE_DISCOVER_AGENT, 238 sizeof(__le32), sizeof(*agent_info), &t); 239 if (ret) 240 return ret; 241 242 put_unaligned_le32(id, t->tx.buf); 243 244 ret = ph->xops->do_xfer(ph, t); 245 if (!ret) { 246 agent_info = t->rx.buf; 247 strlcpy(name, agent_info->name, SCMI_MAX_STR_SIZE); 248 } 249 250 ph->xops->xfer_put(ph, t); 251 252 return ret; 253 } 254 255 static int scmi_base_error_notify(const struct scmi_protocol_handle *ph, 256 bool enable) 257 { 258 int ret; 259 u32 evt_cntl = enable ? BASE_TP_NOTIFY_ALL : 0; 260 struct scmi_xfer *t; 261 struct scmi_msg_base_error_notify *cfg; 262 263 ret = ph->xops->xfer_get_init(ph, BASE_NOTIFY_ERRORS, 264 sizeof(*cfg), 0, &t); 265 if (ret) 266 return ret; 267 268 cfg = t->tx.buf; 269 cfg->event_control = cpu_to_le32(evt_cntl); 270 271 ret = ph->xops->do_xfer(ph, t); 272 273 ph->xops->xfer_put(ph, t); 274 return ret; 275 } 276 277 static int scmi_base_set_notify_enabled(const struct scmi_protocol_handle *ph, 278 u8 evt_id, u32 src_id, bool enable) 279 { 280 int ret; 281 282 ret = scmi_base_error_notify(ph, enable); 283 if (ret) 284 pr_debug("FAIL_ENABLED - evt[%X] ret:%d\n", evt_id, ret); 285 286 return ret; 287 } 288 289 static void *scmi_base_fill_custom_report(const struct scmi_protocol_handle *ph, 290 u8 evt_id, ktime_t timestamp, 291 const void *payld, size_t payld_sz, 292 void *report, u32 *src_id) 293 { 294 int i; 295 const struct scmi_base_error_notify_payld *p = payld; 296 struct scmi_base_error_report *r = report; 297 298 /* 299 * BaseError notification payload is variable in size but 300 * up to a maximum length determined by the struct ponted by p. 301 * Instead payld_sz is the effective length of this notification 302 * payload so cannot be greater of the maximum allowed size as 303 * pointed by p. 304 */ 305 if (evt_id != SCMI_EVENT_BASE_ERROR_EVENT || sizeof(*p) < payld_sz) 306 return NULL; 307 308 r->timestamp = timestamp; 309 r->agent_id = le32_to_cpu(p->agent_id); 310 r->fatal = IS_FATAL_ERROR(le32_to_cpu(p->error_status)); 311 r->cmd_count = ERROR_CMD_COUNT(le32_to_cpu(p->error_status)); 312 for (i = 0; i < r->cmd_count; i++) 313 r->reports[i] = le64_to_cpu(p->msg_reports[i]); 314 *src_id = 0; 315 316 return r; 317 } 318 319 static const struct scmi_event base_events[] = { 320 { 321 .id = SCMI_EVENT_BASE_ERROR_EVENT, 322 .max_payld_sz = sizeof(struct scmi_base_error_notify_payld), 323 .max_report_sz = sizeof(struct scmi_base_error_report) + 324 SCMI_BASE_MAX_CMD_ERR_COUNT * sizeof(u64), 325 }, 326 }; 327 328 static const struct scmi_event_ops base_event_ops = { 329 .set_notify_enabled = scmi_base_set_notify_enabled, 330 .fill_custom_report = scmi_base_fill_custom_report, 331 }; 332 333 static const struct scmi_protocol_events base_protocol_events = { 334 .queue_sz = 4 * SCMI_PROTO_QUEUE_SZ, 335 .ops = &base_event_ops, 336 .evts = base_events, 337 .num_events = ARRAY_SIZE(base_events), 338 .num_sources = SCMI_BASE_NUM_SOURCES, 339 }; 340 341 static int scmi_base_protocol_init(const struct scmi_protocol_handle *ph) 342 { 343 int id, ret; 344 u8 *prot_imp; 345 u32 version; 346 char name[SCMI_MAX_STR_SIZE]; 347 struct device *dev = ph->dev; 348 struct scmi_revision_info *rev = scmi_revision_area_get(ph); 349 350 ret = ph->xops->version_get(ph, &version); 351 if (ret) 352 return ret; 353 354 prot_imp = devm_kcalloc(dev, MAX_PROTOCOLS_IMP, sizeof(u8), GFP_KERNEL); 355 if (!prot_imp) 356 return -ENOMEM; 357 358 rev->major_ver = PROTOCOL_REV_MAJOR(version), 359 rev->minor_ver = PROTOCOL_REV_MINOR(version); 360 ph->set_priv(ph, rev); 361 362 scmi_base_attributes_get(ph); 363 scmi_base_vendor_id_get(ph, false); 364 scmi_base_vendor_id_get(ph, true); 365 scmi_base_implementation_version_get(ph); 366 scmi_base_implementation_list_get(ph, prot_imp); 367 368 scmi_setup_protocol_implemented(ph, prot_imp); 369 370 dev_info(dev, "SCMI Protocol v%d.%d '%s:%s' Firmware version 0x%x\n", 371 rev->major_ver, rev->minor_ver, rev->vendor_id, 372 rev->sub_vendor_id, rev->impl_ver); 373 dev_dbg(dev, "Found %d protocol(s) %d agent(s)\n", rev->num_protocols, 374 rev->num_agents); 375 376 for (id = 0; id < rev->num_agents; id++) { 377 scmi_base_discover_agent_get(ph, id, name); 378 dev_dbg(dev, "Agent %d: %s\n", id, name); 379 } 380 381 return 0; 382 } 383 384 static const struct scmi_protocol scmi_base = { 385 .id = SCMI_PROTOCOL_BASE, 386 .owner = NULL, 387 .instance_init = &scmi_base_protocol_init, 388 .ops = NULL, 389 .events = &base_protocol_events, 390 }; 391 392 DEFINE_SCMI_PROTOCOL_REGISTER_UNREGISTER(base, scmi_base) 393