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