1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * System Control and Management Interface (SCMI) Reset Protocol 4 * 5 * Copyright (C) 2019 ARM Ltd. 6 */ 7 8 #define pr_fmt(fmt) "SCMI Notifications RESET - " fmt 9 10 #include <linux/scmi_protocol.h> 11 12 #include "common.h" 13 #include "notify.h" 14 15 enum scmi_reset_protocol_cmd { 16 RESET_DOMAIN_ATTRIBUTES = 0x3, 17 RESET = 0x4, 18 RESET_NOTIFY = 0x5, 19 }; 20 21 #define NUM_RESET_DOMAIN_MASK 0xffff 22 #define RESET_NOTIFY_ENABLE BIT(0) 23 24 struct scmi_msg_resp_reset_domain_attributes { 25 __le32 attributes; 26 #define SUPPORTS_ASYNC_RESET(x) ((x) & BIT(31)) 27 #define SUPPORTS_NOTIFY_RESET(x) ((x) & BIT(30)) 28 __le32 latency; 29 u8 name[SCMI_MAX_STR_SIZE]; 30 }; 31 32 struct scmi_msg_reset_domain_reset { 33 __le32 domain_id; 34 __le32 flags; 35 #define AUTONOMOUS_RESET BIT(0) 36 #define EXPLICIT_RESET_ASSERT BIT(1) 37 #define ASYNCHRONOUS_RESET BIT(2) 38 __le32 reset_state; 39 #define ARCH_RESET_TYPE BIT(31) 40 #define COLD_RESET_STATE BIT(0) 41 #define ARCH_COLD_RESET (ARCH_RESET_TYPE | COLD_RESET_STATE) 42 }; 43 44 struct scmi_msg_reset_notify { 45 __le32 id; 46 __le32 event_control; 47 #define RESET_TP_NOTIFY_ALL BIT(0) 48 }; 49 50 struct scmi_reset_issued_notify_payld { 51 __le32 agent_id; 52 __le32 domain_id; 53 __le32 reset_state; 54 }; 55 56 struct reset_dom_info { 57 bool async_reset; 58 bool reset_notify; 59 u32 latency_us; 60 char name[SCMI_MAX_STR_SIZE]; 61 }; 62 63 struct scmi_reset_info { 64 u32 version; 65 int num_domains; 66 struct reset_dom_info *dom_info; 67 }; 68 69 static int scmi_reset_attributes_get(const struct scmi_handle *handle, 70 struct scmi_reset_info *pi) 71 { 72 int ret; 73 struct scmi_xfer *t; 74 u32 attr; 75 76 ret = scmi_xfer_get_init(handle, PROTOCOL_ATTRIBUTES, 77 SCMI_PROTOCOL_RESET, 0, sizeof(attr), &t); 78 if (ret) 79 return ret; 80 81 ret = scmi_do_xfer(handle, t); 82 if (!ret) { 83 attr = get_unaligned_le32(t->rx.buf); 84 pi->num_domains = attr & NUM_RESET_DOMAIN_MASK; 85 } 86 87 scmi_xfer_put(handle, t); 88 return ret; 89 } 90 91 static int 92 scmi_reset_domain_attributes_get(const struct scmi_handle *handle, u32 domain, 93 struct reset_dom_info *dom_info) 94 { 95 int ret; 96 struct scmi_xfer *t; 97 struct scmi_msg_resp_reset_domain_attributes *attr; 98 99 ret = scmi_xfer_get_init(handle, RESET_DOMAIN_ATTRIBUTES, 100 SCMI_PROTOCOL_RESET, sizeof(domain), 101 sizeof(*attr), &t); 102 if (ret) 103 return ret; 104 105 put_unaligned_le32(domain, t->tx.buf); 106 attr = t->rx.buf; 107 108 ret = scmi_do_xfer(handle, t); 109 if (!ret) { 110 u32 attributes = le32_to_cpu(attr->attributes); 111 112 dom_info->async_reset = SUPPORTS_ASYNC_RESET(attributes); 113 dom_info->reset_notify = SUPPORTS_NOTIFY_RESET(attributes); 114 dom_info->latency_us = le32_to_cpu(attr->latency); 115 if (dom_info->latency_us == U32_MAX) 116 dom_info->latency_us = 0; 117 strlcpy(dom_info->name, attr->name, SCMI_MAX_STR_SIZE); 118 } 119 120 scmi_xfer_put(handle, t); 121 return ret; 122 } 123 124 static int scmi_reset_num_domains_get(const struct scmi_handle *handle) 125 { 126 struct scmi_reset_info *pi = handle->reset_priv; 127 128 return pi->num_domains; 129 } 130 131 static char *scmi_reset_name_get(const struct scmi_handle *handle, u32 domain) 132 { 133 struct scmi_reset_info *pi = handle->reset_priv; 134 struct reset_dom_info *dom = pi->dom_info + domain; 135 136 return dom->name; 137 } 138 139 static int scmi_reset_latency_get(const struct scmi_handle *handle, u32 domain) 140 { 141 struct scmi_reset_info *pi = handle->reset_priv; 142 struct reset_dom_info *dom = pi->dom_info + domain; 143 144 return dom->latency_us; 145 } 146 147 static int scmi_domain_reset(const struct scmi_handle *handle, u32 domain, 148 u32 flags, u32 state) 149 { 150 int ret; 151 struct scmi_xfer *t; 152 struct scmi_msg_reset_domain_reset *dom; 153 struct scmi_reset_info *pi = handle->reset_priv; 154 struct reset_dom_info *rdom = pi->dom_info + domain; 155 156 if (rdom->async_reset) 157 flags |= ASYNCHRONOUS_RESET; 158 159 ret = scmi_xfer_get_init(handle, RESET, SCMI_PROTOCOL_RESET, 160 sizeof(*dom), 0, &t); 161 if (ret) 162 return ret; 163 164 dom = t->tx.buf; 165 dom->domain_id = cpu_to_le32(domain); 166 dom->flags = cpu_to_le32(flags); 167 dom->reset_state = cpu_to_le32(state); 168 169 if (rdom->async_reset) 170 ret = scmi_do_xfer_with_response(handle, t); 171 else 172 ret = scmi_do_xfer(handle, t); 173 174 scmi_xfer_put(handle, t); 175 return ret; 176 } 177 178 static int scmi_reset_domain_reset(const struct scmi_handle *handle, u32 domain) 179 { 180 return scmi_domain_reset(handle, domain, AUTONOMOUS_RESET, 181 ARCH_COLD_RESET); 182 } 183 184 static int 185 scmi_reset_domain_assert(const struct scmi_handle *handle, u32 domain) 186 { 187 return scmi_domain_reset(handle, domain, EXPLICIT_RESET_ASSERT, 188 ARCH_COLD_RESET); 189 } 190 191 static int 192 scmi_reset_domain_deassert(const struct scmi_handle *handle, u32 domain) 193 { 194 return scmi_domain_reset(handle, domain, 0, ARCH_COLD_RESET); 195 } 196 197 static struct scmi_reset_ops reset_ops = { 198 .num_domains_get = scmi_reset_num_domains_get, 199 .name_get = scmi_reset_name_get, 200 .latency_get = scmi_reset_latency_get, 201 .reset = scmi_reset_domain_reset, 202 .assert = scmi_reset_domain_assert, 203 .deassert = scmi_reset_domain_deassert, 204 }; 205 206 static int scmi_reset_notify(const struct scmi_handle *handle, u32 domain_id, 207 bool enable) 208 { 209 int ret; 210 u32 evt_cntl = enable ? RESET_TP_NOTIFY_ALL : 0; 211 struct scmi_xfer *t; 212 struct scmi_msg_reset_notify *cfg; 213 214 ret = scmi_xfer_get_init(handle, RESET_NOTIFY, 215 SCMI_PROTOCOL_RESET, sizeof(*cfg), 0, &t); 216 if (ret) 217 return ret; 218 219 cfg = t->tx.buf; 220 cfg->id = cpu_to_le32(domain_id); 221 cfg->event_control = cpu_to_le32(evt_cntl); 222 223 ret = scmi_do_xfer(handle, t); 224 225 scmi_xfer_put(handle, t); 226 return ret; 227 } 228 229 static int scmi_reset_set_notify_enabled(const struct scmi_handle *handle, 230 u8 evt_id, u32 src_id, bool enable) 231 { 232 int ret; 233 234 ret = scmi_reset_notify(handle, src_id, enable); 235 if (ret) 236 pr_debug("FAIL_ENABLED - evt[%X] dom[%d] - ret:%d\n", 237 evt_id, src_id, ret); 238 239 return ret; 240 } 241 242 static void *scmi_reset_fill_custom_report(const struct scmi_handle *handle, 243 u8 evt_id, ktime_t timestamp, 244 const void *payld, size_t payld_sz, 245 void *report, u32 *src_id) 246 { 247 const struct scmi_reset_issued_notify_payld *p = payld; 248 struct scmi_reset_issued_report *r = report; 249 250 if (evt_id != SCMI_EVENT_RESET_ISSUED || sizeof(*p) != payld_sz) 251 return NULL; 252 253 r->timestamp = timestamp; 254 r->agent_id = le32_to_cpu(p->agent_id); 255 r->domain_id = le32_to_cpu(p->domain_id); 256 r->reset_state = le32_to_cpu(p->reset_state); 257 *src_id = r->domain_id; 258 259 return r; 260 } 261 262 static const struct scmi_event reset_events[] = { 263 { 264 .id = SCMI_EVENT_RESET_ISSUED, 265 .max_payld_sz = sizeof(struct scmi_reset_issued_notify_payld), 266 .max_report_sz = sizeof(struct scmi_reset_issued_report), 267 }, 268 }; 269 270 static const struct scmi_event_ops reset_event_ops = { 271 .set_notify_enabled = scmi_reset_set_notify_enabled, 272 .fill_custom_report = scmi_reset_fill_custom_report, 273 }; 274 275 static int scmi_reset_protocol_init(struct scmi_handle *handle) 276 { 277 int domain; 278 u32 version; 279 struct scmi_reset_info *pinfo; 280 281 scmi_version_get(handle, SCMI_PROTOCOL_RESET, &version); 282 283 dev_dbg(handle->dev, "Reset Version %d.%d\n", 284 PROTOCOL_REV_MAJOR(version), PROTOCOL_REV_MINOR(version)); 285 286 pinfo = devm_kzalloc(handle->dev, sizeof(*pinfo), GFP_KERNEL); 287 if (!pinfo) 288 return -ENOMEM; 289 290 scmi_reset_attributes_get(handle, pinfo); 291 292 pinfo->dom_info = devm_kcalloc(handle->dev, pinfo->num_domains, 293 sizeof(*pinfo->dom_info), GFP_KERNEL); 294 if (!pinfo->dom_info) 295 return -ENOMEM; 296 297 for (domain = 0; domain < pinfo->num_domains; domain++) { 298 struct reset_dom_info *dom = pinfo->dom_info + domain; 299 300 scmi_reset_domain_attributes_get(handle, domain, dom); 301 } 302 303 scmi_register_protocol_events(handle, 304 SCMI_PROTOCOL_RESET, SCMI_PROTO_QUEUE_SZ, 305 &reset_event_ops, reset_events, 306 ARRAY_SIZE(reset_events), 307 pinfo->num_domains); 308 309 pinfo->version = version; 310 handle->reset_ops = &reset_ops; 311 handle->reset_priv = pinfo; 312 313 return 0; 314 } 315 316 static int __init scmi_reset_init(void) 317 { 318 return scmi_protocol_register(SCMI_PROTOCOL_RESET, 319 &scmi_reset_protocol_init); 320 } 321 subsys_initcall(scmi_reset_init); 322