1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * System Control and Management Interface (SCMI) Voltage Protocol 4 * 5 * Copyright (C) 2020-2022 ARM Ltd. 6 */ 7 8 #include <linux/module.h> 9 #include <linux/scmi_protocol.h> 10 11 #include "protocols.h" 12 13 /* Updated only after ALL the mandatory features for that version are merged */ 14 #define SCMI_PROTOCOL_SUPPORTED_VERSION 0x20001 15 16 #define VOLTAGE_DOMS_NUM_MASK GENMASK(15, 0) 17 #define REMAINING_LEVELS_MASK GENMASK(31, 16) 18 #define RETURNED_LEVELS_MASK GENMASK(11, 0) 19 20 enum scmi_voltage_protocol_cmd { 21 VOLTAGE_DOMAIN_ATTRIBUTES = 0x3, 22 VOLTAGE_DESCRIBE_LEVELS = 0x4, 23 VOLTAGE_CONFIG_SET = 0x5, 24 VOLTAGE_CONFIG_GET = 0x6, 25 VOLTAGE_LEVEL_SET = 0x7, 26 VOLTAGE_LEVEL_GET = 0x8, 27 VOLTAGE_DOMAIN_NAME_GET = 0x09, 28 }; 29 30 #define NUM_VOLTAGE_DOMAINS(x) ((u16)(FIELD_GET(VOLTAGE_DOMS_NUM_MASK, (x)))) 31 32 struct scmi_msg_resp_domain_attributes { 33 __le32 attr; 34 #define SUPPORTS_ASYNC_LEVEL_SET(x) ((x) & BIT(31)) 35 #define SUPPORTS_EXTENDED_NAMES(x) ((x) & BIT(30)) 36 u8 name[SCMI_SHORT_NAME_MAX_SIZE]; 37 }; 38 39 struct scmi_msg_cmd_describe_levels { 40 __le32 domain_id; 41 __le32 level_index; 42 }; 43 44 struct scmi_msg_resp_describe_levels { 45 __le32 flags; 46 #define NUM_REMAINING_LEVELS(f) ((u16)(FIELD_GET(REMAINING_LEVELS_MASK, (f)))) 47 #define NUM_RETURNED_LEVELS(f) ((u16)(FIELD_GET(RETURNED_LEVELS_MASK, (f)))) 48 #define SUPPORTS_SEGMENTED_LEVELS(f) ((f) & BIT(12)) 49 __le32 voltage[]; 50 }; 51 52 struct scmi_msg_cmd_config_set { 53 __le32 domain_id; 54 __le32 config; 55 }; 56 57 struct scmi_msg_cmd_level_set { 58 __le32 domain_id; 59 __le32 flags; 60 __le32 voltage_level; 61 }; 62 63 struct scmi_resp_voltage_level_set_complete { 64 __le32 domain_id; 65 __le32 voltage_level; 66 }; 67 68 struct voltage_info { 69 unsigned int version; 70 unsigned int num_domains; 71 struct scmi_voltage_info *domains; 72 }; 73 74 static int scmi_protocol_attributes_get(const struct scmi_protocol_handle *ph, 75 struct voltage_info *vinfo) 76 { 77 int ret; 78 struct scmi_xfer *t; 79 80 ret = ph->xops->xfer_get_init(ph, PROTOCOL_ATTRIBUTES, 0, 81 sizeof(__le32), &t); 82 if (ret) 83 return ret; 84 85 ret = ph->xops->do_xfer(ph, t); 86 if (!ret) 87 vinfo->num_domains = 88 NUM_VOLTAGE_DOMAINS(get_unaligned_le32(t->rx.buf)); 89 90 ph->xops->xfer_put(ph, t); 91 return ret; 92 } 93 94 static int scmi_init_voltage_levels(struct device *dev, 95 struct scmi_voltage_info *v, 96 u32 num_returned, u32 num_remaining, 97 bool segmented) 98 { 99 u32 num_levels; 100 101 num_levels = num_returned + num_remaining; 102 /* 103 * segmented levels entries are represented by a single triplet 104 * returned all in one go. 105 */ 106 if (!num_levels || 107 (segmented && (num_remaining || num_returned != 3))) { 108 dev_err(dev, 109 "Invalid level descriptor(%d/%d/%d) for voltage dom %d\n", 110 num_levels, num_returned, num_remaining, v->id); 111 return -EINVAL; 112 } 113 114 v->levels_uv = devm_kcalloc(dev, num_levels, sizeof(u32), GFP_KERNEL); 115 if (!v->levels_uv) 116 return -ENOMEM; 117 118 v->num_levels = num_levels; 119 v->segmented = segmented; 120 121 return 0; 122 } 123 124 struct scmi_volt_ipriv { 125 struct device *dev; 126 struct scmi_voltage_info *v; 127 }; 128 129 static void iter_volt_levels_prepare_message(void *message, 130 unsigned int desc_index, 131 const void *priv) 132 { 133 struct scmi_msg_cmd_describe_levels *msg = message; 134 const struct scmi_volt_ipriv *p = priv; 135 136 msg->domain_id = cpu_to_le32(p->v->id); 137 msg->level_index = cpu_to_le32(desc_index); 138 } 139 140 static int iter_volt_levels_update_state(struct scmi_iterator_state *st, 141 const void *response, void *priv) 142 { 143 int ret = 0; 144 u32 flags; 145 const struct scmi_msg_resp_describe_levels *r = response; 146 struct scmi_volt_ipriv *p = priv; 147 148 flags = le32_to_cpu(r->flags); 149 st->num_returned = NUM_RETURNED_LEVELS(flags); 150 st->num_remaining = NUM_REMAINING_LEVELS(flags); 151 152 /* Allocate space for num_levels if not already done */ 153 if (!p->v->num_levels) { 154 ret = scmi_init_voltage_levels(p->dev, p->v, st->num_returned, 155 st->num_remaining, 156 SUPPORTS_SEGMENTED_LEVELS(flags)); 157 if (!ret) 158 st->max_resources = p->v->num_levels; 159 } 160 161 return ret; 162 } 163 164 static int 165 iter_volt_levels_process_response(const struct scmi_protocol_handle *ph, 166 const void *response, 167 struct scmi_iterator_state *st, void *priv) 168 { 169 s32 val; 170 const struct scmi_msg_resp_describe_levels *r = response; 171 struct scmi_volt_ipriv *p = priv; 172 173 val = (s32)le32_to_cpu(r->voltage[st->loop_idx]); 174 p->v->levels_uv[st->desc_index + st->loop_idx] = val; 175 if (val < 0) 176 p->v->negative_volts_allowed = true; 177 178 return 0; 179 } 180 181 static int scmi_voltage_levels_get(const struct scmi_protocol_handle *ph, 182 struct scmi_voltage_info *v) 183 { 184 int ret; 185 void *iter; 186 struct scmi_iterator_ops ops = { 187 .prepare_message = iter_volt_levels_prepare_message, 188 .update_state = iter_volt_levels_update_state, 189 .process_response = iter_volt_levels_process_response, 190 }; 191 struct scmi_volt_ipriv vpriv = { 192 .dev = ph->dev, 193 .v = v, 194 }; 195 196 iter = ph->hops->iter_response_init(ph, &ops, v->num_levels, 197 VOLTAGE_DESCRIBE_LEVELS, 198 sizeof(struct scmi_msg_cmd_describe_levels), 199 &vpriv); 200 if (IS_ERR(iter)) 201 return PTR_ERR(iter); 202 203 ret = ph->hops->iter_response_run(iter); 204 if (ret) { 205 v->num_levels = 0; 206 devm_kfree(ph->dev, v->levels_uv); 207 } 208 209 return ret; 210 } 211 212 static int scmi_voltage_descriptors_get(const struct scmi_protocol_handle *ph, 213 struct voltage_info *vinfo) 214 { 215 int ret, dom; 216 struct scmi_xfer *td; 217 struct scmi_msg_resp_domain_attributes *resp_dom; 218 219 ret = ph->xops->xfer_get_init(ph, VOLTAGE_DOMAIN_ATTRIBUTES, 220 sizeof(__le32), sizeof(*resp_dom), &td); 221 if (ret) 222 return ret; 223 resp_dom = td->rx.buf; 224 225 for (dom = 0; dom < vinfo->num_domains; dom++) { 226 u32 attributes; 227 struct scmi_voltage_info *v; 228 229 /* Retrieve domain attributes at first ... */ 230 put_unaligned_le32(dom, td->tx.buf); 231 /* Skip domain on comms error */ 232 if (ph->xops->do_xfer(ph, td)) { 233 ph->xops->reset_rx_to_maxsz(ph, td); 234 continue; 235 } 236 237 v = vinfo->domains + dom; 238 v->id = dom; 239 attributes = le32_to_cpu(resp_dom->attr); 240 strscpy(v->name, resp_dom->name, SCMI_SHORT_NAME_MAX_SIZE); 241 242 /* 243 * If supported overwrite short name with the extended one; 244 * on error just carry on and use already provided short name. 245 */ 246 if (PROTOCOL_REV_MAJOR(vinfo->version) >= 0x2) { 247 if (SUPPORTS_EXTENDED_NAMES(attributes)) 248 ph->hops->extended_name_get(ph, 249 VOLTAGE_DOMAIN_NAME_GET, 250 v->id, NULL, v->name, 251 SCMI_MAX_STR_SIZE); 252 if (SUPPORTS_ASYNC_LEVEL_SET(attributes)) 253 v->async_level_set = true; 254 } 255 256 /* Skip invalid voltage descriptors */ 257 scmi_voltage_levels_get(ph, v); 258 } 259 260 ph->xops->xfer_put(ph, td); 261 262 return ret; 263 } 264 265 static int __scmi_voltage_get_u32(const struct scmi_protocol_handle *ph, 266 u8 cmd_id, u32 domain_id, u32 *value) 267 { 268 int ret; 269 struct scmi_xfer *t; 270 struct voltage_info *vinfo = ph->get_priv(ph); 271 272 if (domain_id >= vinfo->num_domains) 273 return -EINVAL; 274 275 ret = ph->xops->xfer_get_init(ph, cmd_id, sizeof(__le32), 0, &t); 276 if (ret) 277 return ret; 278 279 put_unaligned_le32(domain_id, t->tx.buf); 280 ret = ph->xops->do_xfer(ph, t); 281 if (!ret) 282 *value = get_unaligned_le32(t->rx.buf); 283 284 ph->xops->xfer_put(ph, t); 285 return ret; 286 } 287 288 static int scmi_voltage_config_set(const struct scmi_protocol_handle *ph, 289 u32 domain_id, u32 config) 290 { 291 int ret; 292 struct scmi_xfer *t; 293 struct voltage_info *vinfo = ph->get_priv(ph); 294 struct scmi_msg_cmd_config_set *cmd; 295 296 if (domain_id >= vinfo->num_domains) 297 return -EINVAL; 298 299 ret = ph->xops->xfer_get_init(ph, VOLTAGE_CONFIG_SET, 300 sizeof(*cmd), 0, &t); 301 if (ret) 302 return ret; 303 304 cmd = t->tx.buf; 305 cmd->domain_id = cpu_to_le32(domain_id); 306 cmd->config = cpu_to_le32(config & GENMASK(3, 0)); 307 308 ret = ph->xops->do_xfer(ph, t); 309 310 ph->xops->xfer_put(ph, t); 311 return ret; 312 } 313 314 static int scmi_voltage_config_get(const struct scmi_protocol_handle *ph, 315 u32 domain_id, u32 *config) 316 { 317 return __scmi_voltage_get_u32(ph, VOLTAGE_CONFIG_GET, 318 domain_id, config); 319 } 320 321 static int scmi_voltage_level_set(const struct scmi_protocol_handle *ph, 322 u32 domain_id, 323 enum scmi_voltage_level_mode mode, 324 s32 volt_uV) 325 { 326 int ret; 327 struct scmi_xfer *t; 328 struct voltage_info *vinfo = ph->get_priv(ph); 329 struct scmi_msg_cmd_level_set *cmd; 330 struct scmi_voltage_info *v; 331 332 if (domain_id >= vinfo->num_domains) 333 return -EINVAL; 334 335 ret = ph->xops->xfer_get_init(ph, VOLTAGE_LEVEL_SET, 336 sizeof(*cmd), 0, &t); 337 if (ret) 338 return ret; 339 340 v = vinfo->domains + domain_id; 341 342 cmd = t->tx.buf; 343 cmd->domain_id = cpu_to_le32(domain_id); 344 cmd->voltage_level = cpu_to_le32(volt_uV); 345 346 if (!v->async_level_set || mode != SCMI_VOLTAGE_LEVEL_SET_AUTO) { 347 cmd->flags = cpu_to_le32(0x0); 348 ret = ph->xops->do_xfer(ph, t); 349 } else { 350 cmd->flags = cpu_to_le32(0x1); 351 ret = ph->xops->do_xfer_with_response(ph, t); 352 if (!ret) { 353 struct scmi_resp_voltage_level_set_complete *resp; 354 355 resp = t->rx.buf; 356 if (le32_to_cpu(resp->domain_id) == domain_id) 357 dev_dbg(ph->dev, 358 "Voltage domain %d set async to %d\n", 359 v->id, 360 le32_to_cpu(resp->voltage_level)); 361 else 362 ret = -EPROTO; 363 } 364 } 365 366 ph->xops->xfer_put(ph, t); 367 return ret; 368 } 369 370 static int scmi_voltage_level_get(const struct scmi_protocol_handle *ph, 371 u32 domain_id, s32 *volt_uV) 372 { 373 return __scmi_voltage_get_u32(ph, VOLTAGE_LEVEL_GET, 374 domain_id, (u32 *)volt_uV); 375 } 376 377 static const struct scmi_voltage_info * __must_check 378 scmi_voltage_info_get(const struct scmi_protocol_handle *ph, u32 domain_id) 379 { 380 struct voltage_info *vinfo = ph->get_priv(ph); 381 382 if (domain_id >= vinfo->num_domains || 383 !vinfo->domains[domain_id].num_levels) 384 return NULL; 385 386 return vinfo->domains + domain_id; 387 } 388 389 static int scmi_voltage_domains_num_get(const struct scmi_protocol_handle *ph) 390 { 391 struct voltage_info *vinfo = ph->get_priv(ph); 392 393 return vinfo->num_domains; 394 } 395 396 static struct scmi_voltage_proto_ops voltage_proto_ops = { 397 .num_domains_get = scmi_voltage_domains_num_get, 398 .info_get = scmi_voltage_info_get, 399 .config_set = scmi_voltage_config_set, 400 .config_get = scmi_voltage_config_get, 401 .level_set = scmi_voltage_level_set, 402 .level_get = scmi_voltage_level_get, 403 }; 404 405 static int scmi_voltage_protocol_init(const struct scmi_protocol_handle *ph) 406 { 407 int ret; 408 u32 version; 409 struct voltage_info *vinfo; 410 411 ret = ph->xops->version_get(ph, &version); 412 if (ret) 413 return ret; 414 415 dev_dbg(ph->dev, "Voltage Version %d.%d\n", 416 PROTOCOL_REV_MAJOR(version), PROTOCOL_REV_MINOR(version)); 417 418 vinfo = devm_kzalloc(ph->dev, sizeof(*vinfo), GFP_KERNEL); 419 if (!vinfo) 420 return -ENOMEM; 421 vinfo->version = version; 422 423 ret = scmi_protocol_attributes_get(ph, vinfo); 424 if (ret) 425 return ret; 426 427 if (vinfo->num_domains) { 428 vinfo->domains = devm_kcalloc(ph->dev, vinfo->num_domains, 429 sizeof(*vinfo->domains), 430 GFP_KERNEL); 431 if (!vinfo->domains) 432 return -ENOMEM; 433 ret = scmi_voltage_descriptors_get(ph, vinfo); 434 if (ret) 435 return ret; 436 } else { 437 dev_warn(ph->dev, "No Voltage domains found.\n"); 438 } 439 440 return ph->set_priv(ph, vinfo, version); 441 } 442 443 static const struct scmi_protocol scmi_voltage = { 444 .id = SCMI_PROTOCOL_VOLTAGE, 445 .owner = THIS_MODULE, 446 .instance_init = &scmi_voltage_protocol_init, 447 .ops = &voltage_proto_ops, 448 .supported_version = SCMI_PROTOCOL_SUPPORTED_VERSION, 449 }; 450 451 DEFINE_SCMI_PROTOCOL_REGISTER_UNREGISTER(voltage, scmi_voltage) 452