1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * System Control and Management Interface (SCMI) Voltage Protocol 4 * 5 * Copyright (C) 2020 ARM Ltd. 6 */ 7 8 #include <linux/scmi_protocol.h> 9 10 #include "common.h" 11 12 #define VOLTAGE_DOMS_NUM_MASK GENMASK(15, 0) 13 #define REMAINING_LEVELS_MASK GENMASK(31, 16) 14 #define RETURNED_LEVELS_MASK GENMASK(11, 0) 15 16 enum scmi_voltage_protocol_cmd { 17 VOLTAGE_DOMAIN_ATTRIBUTES = 0x3, 18 VOLTAGE_DESCRIBE_LEVELS = 0x4, 19 VOLTAGE_CONFIG_SET = 0x5, 20 VOLTAGE_CONFIG_GET = 0x6, 21 VOLTAGE_LEVEL_SET = 0x7, 22 VOLTAGE_LEVEL_GET = 0x8, 23 }; 24 25 #define NUM_VOLTAGE_DOMAINS(x) ((u16)(FIELD_GET(VOLTAGE_DOMS_NUM_MASK, (x)))) 26 27 struct scmi_msg_resp_domain_attributes { 28 __le32 attr; 29 u8 name[SCMI_MAX_STR_SIZE]; 30 }; 31 32 struct scmi_msg_cmd_describe_levels { 33 __le32 domain_id; 34 __le32 level_index; 35 }; 36 37 struct scmi_msg_resp_describe_levels { 38 __le32 flags; 39 #define NUM_REMAINING_LEVELS(f) ((u16)(FIELD_GET(REMAINING_LEVELS_MASK, (f)))) 40 #define NUM_RETURNED_LEVELS(f) ((u16)(FIELD_GET(RETURNED_LEVELS_MASK, (f)))) 41 #define SUPPORTS_SEGMENTED_LEVELS(f) ((f) & BIT(12)) 42 __le32 voltage[]; 43 }; 44 45 struct scmi_msg_cmd_config_set { 46 __le32 domain_id; 47 __le32 config; 48 }; 49 50 struct scmi_msg_cmd_level_set { 51 __le32 domain_id; 52 __le32 flags; 53 __le32 voltage_level; 54 }; 55 56 struct voltage_info { 57 unsigned int version; 58 unsigned int num_domains; 59 struct scmi_voltage_info *domains; 60 }; 61 62 static int scmi_protocol_attributes_get(const struct scmi_handle *handle, 63 struct voltage_info *vinfo) 64 { 65 int ret; 66 struct scmi_xfer *t; 67 68 ret = scmi_xfer_get_init(handle, PROTOCOL_ATTRIBUTES, 69 SCMI_PROTOCOL_VOLTAGE, 0, sizeof(__le32), &t); 70 if (ret) 71 return ret; 72 73 ret = scmi_do_xfer(handle, t); 74 if (!ret) 75 vinfo->num_domains = 76 NUM_VOLTAGE_DOMAINS(get_unaligned_le32(t->rx.buf)); 77 78 scmi_xfer_put(handle, t); 79 return ret; 80 } 81 82 static int scmi_init_voltage_levels(struct device *dev, 83 struct scmi_voltage_info *v, 84 u32 num_returned, u32 num_remaining, 85 bool segmented) 86 { 87 u32 num_levels; 88 89 num_levels = num_returned + num_remaining; 90 /* 91 * segmented levels entries are represented by a single triplet 92 * returned all in one go. 93 */ 94 if (!num_levels || 95 (segmented && (num_remaining || num_returned != 3))) { 96 dev_err(dev, 97 "Invalid level descriptor(%d/%d/%d) for voltage dom %d\n", 98 num_levels, num_returned, num_remaining, v->id); 99 return -EINVAL; 100 } 101 102 v->levels_uv = devm_kcalloc(dev, num_levels, sizeof(u32), GFP_KERNEL); 103 if (!v->levels_uv) 104 return -ENOMEM; 105 106 v->num_levels = num_levels; 107 v->segmented = segmented; 108 109 return 0; 110 } 111 112 static int scmi_voltage_descriptors_get(const struct scmi_handle *handle, 113 struct voltage_info *vinfo) 114 { 115 int ret, dom; 116 struct scmi_xfer *td, *tl; 117 struct device *dev = handle->dev; 118 struct scmi_msg_resp_domain_attributes *resp_dom; 119 struct scmi_msg_resp_describe_levels *resp_levels; 120 121 ret = scmi_xfer_get_init(handle, VOLTAGE_DOMAIN_ATTRIBUTES, 122 SCMI_PROTOCOL_VOLTAGE, sizeof(__le32), 123 sizeof(*resp_dom), &td); 124 if (ret) 125 return ret; 126 resp_dom = td->rx.buf; 127 128 ret = scmi_xfer_get_init(handle, VOLTAGE_DESCRIBE_LEVELS, 129 SCMI_PROTOCOL_VOLTAGE, sizeof(__le64), 0, &tl); 130 if (ret) 131 goto outd; 132 resp_levels = tl->rx.buf; 133 134 for (dom = 0; dom < vinfo->num_domains; dom++) { 135 u32 desc_index = 0; 136 u16 num_returned = 0, num_remaining = 0; 137 struct scmi_msg_cmd_describe_levels *cmd; 138 struct scmi_voltage_info *v; 139 140 /* Retrieve domain attributes at first ... */ 141 put_unaligned_le32(dom, td->tx.buf); 142 ret = scmi_do_xfer(handle, td); 143 /* Skip domain on comms error */ 144 if (ret) 145 continue; 146 147 v = vinfo->domains + dom; 148 v->id = dom; 149 v->attributes = le32_to_cpu(resp_dom->attr); 150 strlcpy(v->name, resp_dom->name, SCMI_MAX_STR_SIZE); 151 152 cmd = tl->tx.buf; 153 /* ...then retrieve domain levels descriptions */ 154 do { 155 u32 flags; 156 int cnt; 157 158 cmd->domain_id = cpu_to_le32(v->id); 159 cmd->level_index = desc_index; 160 ret = scmi_do_xfer(handle, tl); 161 if (ret) 162 break; 163 164 flags = le32_to_cpu(resp_levels->flags); 165 num_returned = NUM_RETURNED_LEVELS(flags); 166 num_remaining = NUM_REMAINING_LEVELS(flags); 167 168 /* Allocate space for num_levels if not already done */ 169 if (!v->num_levels) { 170 ret = scmi_init_voltage_levels(dev, v, 171 num_returned, 172 num_remaining, 173 SUPPORTS_SEGMENTED_LEVELS(flags)); 174 if (ret) 175 break; 176 } 177 178 if (desc_index + num_returned > v->num_levels) { 179 dev_err(handle->dev, 180 "No. of voltage levels can't exceed %d\n", 181 v->num_levels); 182 ret = -EINVAL; 183 break; 184 } 185 186 for (cnt = 0; cnt < num_returned; cnt++) { 187 s32 val; 188 189 val = 190 (s32)le32_to_cpu(resp_levels->voltage[cnt]); 191 v->levels_uv[desc_index + cnt] = val; 192 if (val < 0) 193 v->negative_volts_allowed = true; 194 } 195 196 desc_index += num_returned; 197 198 scmi_reset_rx_to_maxsz(handle, tl); 199 /* check both to avoid infinite loop due to buggy fw */ 200 } while (num_returned && num_remaining); 201 202 if (ret) { 203 v->num_levels = 0; 204 devm_kfree(dev, v->levels_uv); 205 } 206 207 scmi_reset_rx_to_maxsz(handle, td); 208 } 209 210 scmi_xfer_put(handle, tl); 211 outd: 212 scmi_xfer_put(handle, td); 213 214 return ret; 215 } 216 217 static int __scmi_voltage_get_u32(const struct scmi_handle *handle, 218 u8 cmd_id, u32 domain_id, u32 *value) 219 { 220 int ret; 221 struct scmi_xfer *t; 222 struct voltage_info *vinfo = handle->voltage_priv; 223 224 if (domain_id >= vinfo->num_domains) 225 return -EINVAL; 226 227 ret = scmi_xfer_get_init(handle, cmd_id, 228 SCMI_PROTOCOL_VOLTAGE, 229 sizeof(__le32), 0, &t); 230 if (ret) 231 return ret; 232 233 put_unaligned_le32(domain_id, t->tx.buf); 234 ret = scmi_do_xfer(handle, t); 235 if (!ret) 236 *value = get_unaligned_le32(t->rx.buf); 237 238 scmi_xfer_put(handle, t); 239 return ret; 240 } 241 242 static int scmi_voltage_config_set(const struct scmi_handle *handle, 243 u32 domain_id, u32 config) 244 { 245 int ret; 246 struct scmi_xfer *t; 247 struct voltage_info *vinfo = handle->voltage_priv; 248 struct scmi_msg_cmd_config_set *cmd; 249 250 if (domain_id >= vinfo->num_domains) 251 return -EINVAL; 252 253 ret = scmi_xfer_get_init(handle, VOLTAGE_CONFIG_SET, 254 SCMI_PROTOCOL_VOLTAGE, 255 sizeof(*cmd), 0, &t); 256 if (ret) 257 return ret; 258 259 cmd = t->tx.buf; 260 cmd->domain_id = cpu_to_le32(domain_id); 261 cmd->config = cpu_to_le32(config & GENMASK(3, 0)); 262 263 ret = scmi_do_xfer(handle, t); 264 265 scmi_xfer_put(handle, t); 266 return ret; 267 } 268 269 static int scmi_voltage_config_get(const struct scmi_handle *handle, 270 u32 domain_id, u32 *config) 271 { 272 return __scmi_voltage_get_u32(handle, VOLTAGE_CONFIG_GET, 273 domain_id, config); 274 } 275 276 static int scmi_voltage_level_set(const struct scmi_handle *handle, 277 u32 domain_id, u32 flags, s32 volt_uV) 278 { 279 int ret; 280 struct scmi_xfer *t; 281 struct voltage_info *vinfo = handle->voltage_priv; 282 struct scmi_msg_cmd_level_set *cmd; 283 284 if (domain_id >= vinfo->num_domains) 285 return -EINVAL; 286 287 ret = scmi_xfer_get_init(handle, VOLTAGE_LEVEL_SET, 288 SCMI_PROTOCOL_VOLTAGE, 289 sizeof(*cmd), 0, &t); 290 if (ret) 291 return ret; 292 293 cmd = t->tx.buf; 294 cmd->domain_id = cpu_to_le32(domain_id); 295 cmd->flags = cpu_to_le32(flags); 296 cmd->voltage_level = cpu_to_le32(volt_uV); 297 298 ret = scmi_do_xfer(handle, t); 299 300 scmi_xfer_put(handle, t); 301 return ret; 302 } 303 304 static int scmi_voltage_level_get(const struct scmi_handle *handle, 305 u32 domain_id, s32 *volt_uV) 306 { 307 return __scmi_voltage_get_u32(handle, VOLTAGE_LEVEL_GET, 308 domain_id, (u32 *)volt_uV); 309 } 310 311 static const struct scmi_voltage_info * __must_check 312 scmi_voltage_info_get(const struct scmi_handle *handle, u32 domain_id) 313 { 314 struct voltage_info *vinfo = handle->voltage_priv; 315 316 if (domain_id >= vinfo->num_domains || 317 !vinfo->domains[domain_id].num_levels) 318 return NULL; 319 320 return vinfo->domains + domain_id; 321 } 322 323 static int scmi_voltage_domains_num_get(const struct scmi_handle *handle) 324 { 325 struct voltage_info *vinfo = handle->voltage_priv; 326 327 return vinfo->num_domains; 328 } 329 330 static struct scmi_voltage_ops voltage_ops = { 331 .num_domains_get = scmi_voltage_domains_num_get, 332 .info_get = scmi_voltage_info_get, 333 .config_set = scmi_voltage_config_set, 334 .config_get = scmi_voltage_config_get, 335 .level_set = scmi_voltage_level_set, 336 .level_get = scmi_voltage_level_get, 337 }; 338 339 static int scmi_voltage_protocol_init(struct scmi_handle *handle) 340 { 341 int ret; 342 u32 version; 343 struct voltage_info *vinfo; 344 345 ret = scmi_version_get(handle, SCMI_PROTOCOL_VOLTAGE, &version); 346 if (ret) 347 return ret; 348 349 dev_dbg(handle->dev, "Voltage Version %d.%d\n", 350 PROTOCOL_REV_MAJOR(version), PROTOCOL_REV_MINOR(version)); 351 352 vinfo = devm_kzalloc(handle->dev, sizeof(*vinfo), GFP_KERNEL); 353 if (!vinfo) 354 return -ENOMEM; 355 vinfo->version = version; 356 357 ret = scmi_protocol_attributes_get(handle, vinfo); 358 if (ret) 359 return ret; 360 361 if (vinfo->num_domains) { 362 vinfo->domains = devm_kcalloc(handle->dev, vinfo->num_domains, 363 sizeof(*vinfo->domains), 364 GFP_KERNEL); 365 if (!vinfo->domains) 366 return -ENOMEM; 367 ret = scmi_voltage_descriptors_get(handle, vinfo); 368 if (ret) 369 return ret; 370 } else { 371 dev_warn(handle->dev, "No Voltage domains found.\n"); 372 } 373 374 handle->voltage_ops = &voltage_ops; 375 handle->voltage_priv = vinfo; 376 377 return 0; 378 } 379 380 DEFINE_SCMI_PROTOCOL_REGISTER_UNREGISTER(SCMI_PROTOCOL_VOLTAGE, voltage) 381