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 0x20000 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 20enum 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 32struct 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 39struct scmi_msg_cmd_describe_levels { 40 __le32 domain_id; 41 __le32 level_index; 42}; 43 44struct 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 52struct scmi_msg_cmd_config_set { 53 __le32 domain_id; 54 __le32 config; 55}; 56 57struct scmi_msg_cmd_level_set { 58 __le32 domain_id; 59 __le32 flags; 60 __le32 voltage_level; 61}; 62 63struct scmi_resp_voltage_level_set_complete { 64 __le32 domain_id; 65 __le32 voltage_level; 66}; 67 68struct voltage_info { 69 unsigned int version; 70 unsigned int num_domains; 71 struct scmi_voltage_info *domains; 72}; 73 74static 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 94static 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 124struct scmi_volt_ipriv { 125 struct device *dev; 126 struct scmi_voltage_info *v; 127}; 128 129static 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 140static 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 164static int 165iter_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 181static 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 212static 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 continue; 234 235 v = vinfo->domains + dom; 236 v->id = dom; 237 attributes = le32_to_cpu(resp_dom->attr); 238 strscpy(v->name, resp_dom->name, SCMI_SHORT_NAME_MAX_SIZE); 239 240 /* 241 * If supported overwrite short name with the extended one; 242 * on error just carry on and use already provided short name. 243 */ 244 if (PROTOCOL_REV_MAJOR(vinfo->version) >= 0x2) { 245 if (SUPPORTS_EXTENDED_NAMES(attributes)) 246 ph->hops->extended_name_get(ph, 247 VOLTAGE_DOMAIN_NAME_GET, 248 v->id, NULL, v->name, 249 SCMI_MAX_STR_SIZE); 250 if (SUPPORTS_ASYNC_LEVEL_SET(attributes)) 251 v->async_level_set = true; 252 } 253 254 /* Skip invalid voltage descriptors */ 255 scmi_voltage_levels_get(ph, v); 256 } 257 258 ph->xops->xfer_put(ph, td); 259 260 return ret; 261} 262 263static int __scmi_voltage_get_u32(const struct scmi_protocol_handle *ph, 264 u8 cmd_id, u32 domain_id, u32 *value) 265{ 266 int ret; 267 struct scmi_xfer *t; 268 struct voltage_info *vinfo = ph->get_priv(ph); 269 270 if (domain_id >= vinfo->num_domains) 271 return -EINVAL; 272 273 ret = ph->xops->xfer_get_init(ph, cmd_id, sizeof(__le32), 0, &t); 274 if (ret) 275 return ret; 276 277 put_unaligned_le32(domain_id, t->tx.buf); 278 ret = ph->xops->do_xfer(ph, t); 279 if (!ret) 280 *value = get_unaligned_le32(t->rx.buf); 281 282 ph->xops->xfer_put(ph, t); 283 return ret; 284} 285 286static int scmi_voltage_config_set(const struct scmi_protocol_handle *ph, 287 u32 domain_id, u32 config) 288{ 289 int ret; 290 struct scmi_xfer *t; 291 struct voltage_info *vinfo = ph->get_priv(ph); 292 struct scmi_msg_cmd_config_set *cmd; 293 294 if (domain_id >= vinfo->num_domains) 295 return -EINVAL; 296 297 ret = ph->xops->xfer_get_init(ph, VOLTAGE_CONFIG_SET, 298 sizeof(*cmd), 0, &t); 299 if (ret) 300 return ret; 301 302 cmd = t->tx.buf; 303 cmd->domain_id = cpu_to_le32(domain_id); 304 cmd->config = cpu_to_le32(config & GENMASK(3, 0)); 305 306 ret = ph->xops->do_xfer(ph, t); 307 308 ph->xops->xfer_put(ph, t); 309 return ret; 310} 311 312static int scmi_voltage_config_get(const struct scmi_protocol_handle *ph, 313 u32 domain_id, u32 *config) 314{ 315 return __scmi_voltage_get_u32(ph, VOLTAGE_CONFIG_GET, 316 domain_id, config); 317} 318 319static int scmi_voltage_level_set(const struct scmi_protocol_handle *ph, 320 u32 domain_id, 321 enum scmi_voltage_level_mode mode, 322 s32 volt_uV) 323{ 324 int ret; 325 struct scmi_xfer *t; 326 struct voltage_info *vinfo = ph->get_priv(ph); 327 struct scmi_msg_cmd_level_set *cmd; 328 struct scmi_voltage_info *v; 329 330 if (domain_id >= vinfo->num_domains) 331 return -EINVAL; 332 333 ret = ph->xops->xfer_get_init(ph, VOLTAGE_LEVEL_SET, 334 sizeof(*cmd), 0, &t); 335 if (ret) 336 return ret; 337 338 v = vinfo->domains + domain_id; 339 340 cmd = t->tx.buf; 341 cmd->domain_id = cpu_to_le32(domain_id); 342 cmd->voltage_level = cpu_to_le32(volt_uV); 343 344 if (!v->async_level_set || mode != SCMI_VOLTAGE_LEVEL_SET_AUTO) { 345 cmd->flags = cpu_to_le32(0x0); 346 ret = ph->xops->do_xfer(ph, t); 347 } else { 348 cmd->flags = cpu_to_le32(0x1); 349 ret = ph->xops->do_xfer_with_response(ph, t); 350 if (!ret) { 351 struct scmi_resp_voltage_level_set_complete *resp; 352 353 resp = t->rx.buf; 354 if (le32_to_cpu(resp->domain_id) == domain_id) 355 dev_dbg(ph->dev, 356 "Voltage domain %d set async to %d\n", 357 v->id, 358 le32_to_cpu(resp->voltage_level)); 359 else 360 ret = -EPROTO; 361 } 362 } 363 364 ph->xops->xfer_put(ph, t); 365 return ret; 366} 367 368static int scmi_voltage_level_get(const struct scmi_protocol_handle *ph, 369 u32 domain_id, s32 *volt_uV) 370{ 371 return __scmi_voltage_get_u32(ph, VOLTAGE_LEVEL_GET, 372 domain_id, (u32 *)volt_uV); 373} 374 375static const struct scmi_voltage_info * __must_check 376scmi_voltage_info_get(const struct scmi_protocol_handle *ph, u32 domain_id) 377{ 378 struct voltage_info *vinfo = ph->get_priv(ph); 379 380 if (domain_id >= vinfo->num_domains || 381 !vinfo->domains[domain_id].num_levels) 382 return NULL; 383 384 return vinfo->domains + domain_id; 385} 386 387static int scmi_voltage_domains_num_get(const struct scmi_protocol_handle *ph) 388{ 389 struct voltage_info *vinfo = ph->get_priv(ph); 390 391 return vinfo->num_domains; 392} 393 394static struct scmi_voltage_proto_ops voltage_proto_ops = { 395 .num_domains_get = scmi_voltage_domains_num_get, 396 .info_get = scmi_voltage_info_get, 397 .config_set = scmi_voltage_config_set, 398 .config_get = scmi_voltage_config_get, 399 .level_set = scmi_voltage_level_set, 400 .level_get = scmi_voltage_level_get, 401}; 402 403static int scmi_voltage_protocol_init(const struct scmi_protocol_handle *ph) 404{ 405 int ret; 406 u32 version; 407 struct voltage_info *vinfo; 408 409 ret = ph->xops->version_get(ph, &version); 410 if (ret) 411 return ret; 412 413 dev_dbg(ph->dev, "Voltage Version %d.%d\n", 414 PROTOCOL_REV_MAJOR(version), PROTOCOL_REV_MINOR(version)); 415 416 vinfo = devm_kzalloc(ph->dev, sizeof(*vinfo), GFP_KERNEL); 417 if (!vinfo) 418 return -ENOMEM; 419 vinfo->version = version; 420 421 ret = scmi_protocol_attributes_get(ph, vinfo); 422 if (ret) 423 return ret; 424 425 if (vinfo->num_domains) { 426 vinfo->domains = devm_kcalloc(ph->dev, vinfo->num_domains, 427 sizeof(*vinfo->domains), 428 GFP_KERNEL); 429 if (!vinfo->domains) 430 return -ENOMEM; 431 ret = scmi_voltage_descriptors_get(ph, vinfo); 432 if (ret) 433 return ret; 434 } else { 435 dev_warn(ph->dev, "No Voltage domains found.\n"); 436 } 437 438 return ph->set_priv(ph, vinfo, version); 439} 440 441static const struct scmi_protocol scmi_voltage = { 442 .id = SCMI_PROTOCOL_VOLTAGE, 443 .owner = THIS_MODULE, 444 .instance_init = &scmi_voltage_protocol_init, 445 .ops = &voltage_proto_ops, 446 .supported_version = SCMI_PROTOCOL_SUPPORTED_VERSION, 447}; 448 449DEFINE_SCMI_PROTOCOL_REGISTER_UNREGISTER(voltage, scmi_voltage) 450