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