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