0001
0002
0003
0004
0005
0006
0007
0008 #include <linux/module.h>
0009 #include <linux/scmi_protocol.h>
0010
0011 #include "protocols.h"
0012
0013 #define VOLTAGE_DOMS_NUM_MASK GENMASK(15, 0)
0014 #define REMAINING_LEVELS_MASK GENMASK(31, 16)
0015 #define RETURNED_LEVELS_MASK GENMASK(11, 0)
0016
0017 enum scmi_voltage_protocol_cmd {
0018 VOLTAGE_DOMAIN_ATTRIBUTES = 0x3,
0019 VOLTAGE_DESCRIBE_LEVELS = 0x4,
0020 VOLTAGE_CONFIG_SET = 0x5,
0021 VOLTAGE_CONFIG_GET = 0x6,
0022 VOLTAGE_LEVEL_SET = 0x7,
0023 VOLTAGE_LEVEL_GET = 0x8,
0024 VOLTAGE_DOMAIN_NAME_GET = 0x09,
0025 };
0026
0027 #define NUM_VOLTAGE_DOMAINS(x) ((u16)(FIELD_GET(VOLTAGE_DOMS_NUM_MASK, (x))))
0028
0029 struct scmi_msg_resp_domain_attributes {
0030 __le32 attr;
0031 #define SUPPORTS_ASYNC_LEVEL_SET(x) ((x) & BIT(31))
0032 #define SUPPORTS_EXTENDED_NAMES(x) ((x) & BIT(30))
0033 u8 name[SCMI_SHORT_NAME_MAX_SIZE];
0034 };
0035
0036 struct scmi_msg_cmd_describe_levels {
0037 __le32 domain_id;
0038 __le32 level_index;
0039 };
0040
0041 struct scmi_msg_resp_describe_levels {
0042 __le32 flags;
0043 #define NUM_REMAINING_LEVELS(f) ((u16)(FIELD_GET(REMAINING_LEVELS_MASK, (f))))
0044 #define NUM_RETURNED_LEVELS(f) ((u16)(FIELD_GET(RETURNED_LEVELS_MASK, (f))))
0045 #define SUPPORTS_SEGMENTED_LEVELS(f) ((f) & BIT(12))
0046 __le32 voltage[];
0047 };
0048
0049 struct scmi_msg_cmd_config_set {
0050 __le32 domain_id;
0051 __le32 config;
0052 };
0053
0054 struct scmi_msg_cmd_level_set {
0055 __le32 domain_id;
0056 __le32 flags;
0057 __le32 voltage_level;
0058 };
0059
0060 struct scmi_resp_voltage_level_set_complete {
0061 __le32 domain_id;
0062 __le32 voltage_level;
0063 };
0064
0065 struct voltage_info {
0066 unsigned int version;
0067 unsigned int num_domains;
0068 struct scmi_voltage_info *domains;
0069 };
0070
0071 static int scmi_protocol_attributes_get(const struct scmi_protocol_handle *ph,
0072 struct voltage_info *vinfo)
0073 {
0074 int ret;
0075 struct scmi_xfer *t;
0076
0077 ret = ph->xops->xfer_get_init(ph, PROTOCOL_ATTRIBUTES, 0,
0078 sizeof(__le32), &t);
0079 if (ret)
0080 return ret;
0081
0082 ret = ph->xops->do_xfer(ph, t);
0083 if (!ret)
0084 vinfo->num_domains =
0085 NUM_VOLTAGE_DOMAINS(get_unaligned_le32(t->rx.buf));
0086
0087 ph->xops->xfer_put(ph, t);
0088 return ret;
0089 }
0090
0091 static int scmi_init_voltage_levels(struct device *dev,
0092 struct scmi_voltage_info *v,
0093 u32 num_returned, u32 num_remaining,
0094 bool segmented)
0095 {
0096 u32 num_levels;
0097
0098 num_levels = num_returned + num_remaining;
0099
0100
0101
0102
0103 if (!num_levels ||
0104 (segmented && (num_remaining || num_returned != 3))) {
0105 dev_err(dev,
0106 "Invalid level descriptor(%d/%d/%d) for voltage dom %d\n",
0107 num_levels, num_returned, num_remaining, v->id);
0108 return -EINVAL;
0109 }
0110
0111 v->levels_uv = devm_kcalloc(dev, num_levels, sizeof(u32), GFP_KERNEL);
0112 if (!v->levels_uv)
0113 return -ENOMEM;
0114
0115 v->num_levels = num_levels;
0116 v->segmented = segmented;
0117
0118 return 0;
0119 }
0120
0121 struct scmi_volt_ipriv {
0122 struct device *dev;
0123 struct scmi_voltage_info *v;
0124 };
0125
0126 static void iter_volt_levels_prepare_message(void *message,
0127 unsigned int desc_index,
0128 const void *priv)
0129 {
0130 struct scmi_msg_cmd_describe_levels *msg = message;
0131 const struct scmi_volt_ipriv *p = priv;
0132
0133 msg->domain_id = cpu_to_le32(p->v->id);
0134 msg->level_index = cpu_to_le32(desc_index);
0135 }
0136
0137 static int iter_volt_levels_update_state(struct scmi_iterator_state *st,
0138 const void *response, void *priv)
0139 {
0140 int ret = 0;
0141 u32 flags;
0142 const struct scmi_msg_resp_describe_levels *r = response;
0143 struct scmi_volt_ipriv *p = priv;
0144
0145 flags = le32_to_cpu(r->flags);
0146 st->num_returned = NUM_RETURNED_LEVELS(flags);
0147 st->num_remaining = NUM_REMAINING_LEVELS(flags);
0148
0149
0150 if (!p->v->num_levels) {
0151 ret = scmi_init_voltage_levels(p->dev, p->v, st->num_returned,
0152 st->num_remaining,
0153 SUPPORTS_SEGMENTED_LEVELS(flags));
0154 if (!ret)
0155 st->max_resources = p->v->num_levels;
0156 }
0157
0158 return ret;
0159 }
0160
0161 static int
0162 iter_volt_levels_process_response(const struct scmi_protocol_handle *ph,
0163 const void *response,
0164 struct scmi_iterator_state *st, void *priv)
0165 {
0166 s32 val;
0167 const struct scmi_msg_resp_describe_levels *r = response;
0168 struct scmi_volt_ipriv *p = priv;
0169
0170 val = (s32)le32_to_cpu(r->voltage[st->loop_idx]);
0171 p->v->levels_uv[st->desc_index + st->loop_idx] = val;
0172 if (val < 0)
0173 p->v->negative_volts_allowed = true;
0174
0175 return 0;
0176 }
0177
0178 static int scmi_voltage_levels_get(const struct scmi_protocol_handle *ph,
0179 struct scmi_voltage_info *v)
0180 {
0181 int ret;
0182 void *iter;
0183 struct scmi_iterator_ops ops = {
0184 .prepare_message = iter_volt_levels_prepare_message,
0185 .update_state = iter_volt_levels_update_state,
0186 .process_response = iter_volt_levels_process_response,
0187 };
0188 struct scmi_volt_ipriv vpriv = {
0189 .dev = ph->dev,
0190 .v = v,
0191 };
0192
0193 iter = ph->hops->iter_response_init(ph, &ops, v->num_levels,
0194 VOLTAGE_DESCRIBE_LEVELS,
0195 sizeof(struct scmi_msg_cmd_describe_levels),
0196 &vpriv);
0197 if (IS_ERR(iter))
0198 return PTR_ERR(iter);
0199
0200 ret = ph->hops->iter_response_run(iter);
0201 if (ret) {
0202 v->num_levels = 0;
0203 devm_kfree(ph->dev, v->levels_uv);
0204 }
0205
0206 return ret;
0207 }
0208
0209 static int scmi_voltage_descriptors_get(const struct scmi_protocol_handle *ph,
0210 struct voltage_info *vinfo)
0211 {
0212 int ret, dom;
0213 struct scmi_xfer *td;
0214 struct scmi_msg_resp_domain_attributes *resp_dom;
0215
0216 ret = ph->xops->xfer_get_init(ph, VOLTAGE_DOMAIN_ATTRIBUTES,
0217 sizeof(__le32), sizeof(*resp_dom), &td);
0218 if (ret)
0219 return ret;
0220 resp_dom = td->rx.buf;
0221
0222 for (dom = 0; dom < vinfo->num_domains; dom++) {
0223 u32 attributes;
0224 struct scmi_voltage_info *v;
0225
0226
0227 put_unaligned_le32(dom, td->tx.buf);
0228
0229 if (ph->xops->do_xfer(ph, td))
0230 continue;
0231
0232 v = vinfo->domains + dom;
0233 v->id = dom;
0234 attributes = le32_to_cpu(resp_dom->attr);
0235 strscpy(v->name, resp_dom->name, SCMI_SHORT_NAME_MAX_SIZE);
0236
0237
0238
0239
0240
0241 if (PROTOCOL_REV_MAJOR(vinfo->version) >= 0x2) {
0242 if (SUPPORTS_EXTENDED_NAMES(attributes))
0243 ph->hops->extended_name_get(ph,
0244 VOLTAGE_DOMAIN_NAME_GET,
0245 v->id, v->name,
0246 SCMI_MAX_STR_SIZE);
0247 if (SUPPORTS_ASYNC_LEVEL_SET(attributes))
0248 v->async_level_set = true;
0249 }
0250
0251
0252 scmi_voltage_levels_get(ph, v);
0253 }
0254
0255 ph->xops->xfer_put(ph, td);
0256
0257 return ret;
0258 }
0259
0260 static int __scmi_voltage_get_u32(const struct scmi_protocol_handle *ph,
0261 u8 cmd_id, u32 domain_id, u32 *value)
0262 {
0263 int ret;
0264 struct scmi_xfer *t;
0265 struct voltage_info *vinfo = ph->get_priv(ph);
0266
0267 if (domain_id >= vinfo->num_domains)
0268 return -EINVAL;
0269
0270 ret = ph->xops->xfer_get_init(ph, cmd_id, sizeof(__le32), 0, &t);
0271 if (ret)
0272 return ret;
0273
0274 put_unaligned_le32(domain_id, t->tx.buf);
0275 ret = ph->xops->do_xfer(ph, t);
0276 if (!ret)
0277 *value = get_unaligned_le32(t->rx.buf);
0278
0279 ph->xops->xfer_put(ph, t);
0280 return ret;
0281 }
0282
0283 static int scmi_voltage_config_set(const struct scmi_protocol_handle *ph,
0284 u32 domain_id, u32 config)
0285 {
0286 int ret;
0287 struct scmi_xfer *t;
0288 struct voltage_info *vinfo = ph->get_priv(ph);
0289 struct scmi_msg_cmd_config_set *cmd;
0290
0291 if (domain_id >= vinfo->num_domains)
0292 return -EINVAL;
0293
0294 ret = ph->xops->xfer_get_init(ph, VOLTAGE_CONFIG_SET,
0295 sizeof(*cmd), 0, &t);
0296 if (ret)
0297 return ret;
0298
0299 cmd = t->tx.buf;
0300 cmd->domain_id = cpu_to_le32(domain_id);
0301 cmd->config = cpu_to_le32(config & GENMASK(3, 0));
0302
0303 ret = ph->xops->do_xfer(ph, t);
0304
0305 ph->xops->xfer_put(ph, t);
0306 return ret;
0307 }
0308
0309 static int scmi_voltage_config_get(const struct scmi_protocol_handle *ph,
0310 u32 domain_id, u32 *config)
0311 {
0312 return __scmi_voltage_get_u32(ph, VOLTAGE_CONFIG_GET,
0313 domain_id, config);
0314 }
0315
0316 static int scmi_voltage_level_set(const struct scmi_protocol_handle *ph,
0317 u32 domain_id,
0318 enum scmi_voltage_level_mode mode,
0319 s32 volt_uV)
0320 {
0321 int ret;
0322 struct scmi_xfer *t;
0323 struct voltage_info *vinfo = ph->get_priv(ph);
0324 struct scmi_msg_cmd_level_set *cmd;
0325 struct scmi_voltage_info *v;
0326
0327 if (domain_id >= vinfo->num_domains)
0328 return -EINVAL;
0329
0330 ret = ph->xops->xfer_get_init(ph, VOLTAGE_LEVEL_SET,
0331 sizeof(*cmd), 0, &t);
0332 if (ret)
0333 return ret;
0334
0335 v = vinfo->domains + domain_id;
0336
0337 cmd = t->tx.buf;
0338 cmd->domain_id = cpu_to_le32(domain_id);
0339 cmd->voltage_level = cpu_to_le32(volt_uV);
0340
0341 if (!v->async_level_set || mode != SCMI_VOLTAGE_LEVEL_SET_AUTO) {
0342 cmd->flags = cpu_to_le32(0x0);
0343 ret = ph->xops->do_xfer(ph, t);
0344 } else {
0345 cmd->flags = cpu_to_le32(0x1);
0346 ret = ph->xops->do_xfer_with_response(ph, t);
0347 if (!ret) {
0348 struct scmi_resp_voltage_level_set_complete *resp;
0349
0350 resp = t->rx.buf;
0351 if (le32_to_cpu(resp->domain_id) == domain_id)
0352 dev_dbg(ph->dev,
0353 "Voltage domain %d set async to %d\n",
0354 v->id,
0355 le32_to_cpu(resp->voltage_level));
0356 else
0357 ret = -EPROTO;
0358 }
0359 }
0360
0361 ph->xops->xfer_put(ph, t);
0362 return ret;
0363 }
0364
0365 static int scmi_voltage_level_get(const struct scmi_protocol_handle *ph,
0366 u32 domain_id, s32 *volt_uV)
0367 {
0368 return __scmi_voltage_get_u32(ph, VOLTAGE_LEVEL_GET,
0369 domain_id, (u32 *)volt_uV);
0370 }
0371
0372 static const struct scmi_voltage_info * __must_check
0373 scmi_voltage_info_get(const struct scmi_protocol_handle *ph, u32 domain_id)
0374 {
0375 struct voltage_info *vinfo = ph->get_priv(ph);
0376
0377 if (domain_id >= vinfo->num_domains ||
0378 !vinfo->domains[domain_id].num_levels)
0379 return NULL;
0380
0381 return vinfo->domains + domain_id;
0382 }
0383
0384 static int scmi_voltage_domains_num_get(const struct scmi_protocol_handle *ph)
0385 {
0386 struct voltage_info *vinfo = ph->get_priv(ph);
0387
0388 return vinfo->num_domains;
0389 }
0390
0391 static struct scmi_voltage_proto_ops voltage_proto_ops = {
0392 .num_domains_get = scmi_voltage_domains_num_get,
0393 .info_get = scmi_voltage_info_get,
0394 .config_set = scmi_voltage_config_set,
0395 .config_get = scmi_voltage_config_get,
0396 .level_set = scmi_voltage_level_set,
0397 .level_get = scmi_voltage_level_get,
0398 };
0399
0400 static int scmi_voltage_protocol_init(const struct scmi_protocol_handle *ph)
0401 {
0402 int ret;
0403 u32 version;
0404 struct voltage_info *vinfo;
0405
0406 ret = ph->xops->version_get(ph, &version);
0407 if (ret)
0408 return ret;
0409
0410 dev_dbg(ph->dev, "Voltage Version %d.%d\n",
0411 PROTOCOL_REV_MAJOR(version), PROTOCOL_REV_MINOR(version));
0412
0413 vinfo = devm_kzalloc(ph->dev, sizeof(*vinfo), GFP_KERNEL);
0414 if (!vinfo)
0415 return -ENOMEM;
0416 vinfo->version = version;
0417
0418 ret = scmi_protocol_attributes_get(ph, vinfo);
0419 if (ret)
0420 return ret;
0421
0422 if (vinfo->num_domains) {
0423 vinfo->domains = devm_kcalloc(ph->dev, vinfo->num_domains,
0424 sizeof(*vinfo->domains),
0425 GFP_KERNEL);
0426 if (!vinfo->domains)
0427 return -ENOMEM;
0428 ret = scmi_voltage_descriptors_get(ph, vinfo);
0429 if (ret)
0430 return ret;
0431 } else {
0432 dev_warn(ph->dev, "No Voltage domains found.\n");
0433 }
0434
0435 return ph->set_priv(ph, vinfo);
0436 }
0437
0438 static const struct scmi_protocol scmi_voltage = {
0439 .id = SCMI_PROTOCOL_VOLTAGE,
0440 .owner = THIS_MODULE,
0441 .instance_init = &scmi_voltage_protocol_init,
0442 .ops = &voltage_proto_ops,
0443 };
0444
0445 DEFINE_SCMI_PROTOCOL_REGISTER_UNREGISTER(voltage, scmi_voltage)