/* * Copyright 2024 NXP * * SPDX-License-Identifier: Apache-2.0 */ #include #include /* TODO: if extended attributes are supported this should be moved * to the header file so that users will have access to it. */ #define SCMI_CLK_CONFIG_EA_MASK GENMASK(23, 16) struct scmi_clock_attributes_reply { int32_t status; uint32_t attributes; }; struct scmi_clock_rate_set_reply { int32_t status; uint32_t rate[2]; }; int scmi_clock_rate_get(struct scmi_protocol *proto, uint32_t clk_id, uint32_t *rate) { struct scmi_message msg, reply; int ret; struct scmi_clock_rate_set_reply reply_buffer; /* sanity checks */ if (!proto || !rate) { return -EINVAL; } if (proto->id != SCMI_PROTOCOL_CLOCK) { return -EINVAL; } msg.hdr = SCMI_MESSAGE_HDR_MAKE(SCMI_CLK_MSG_CLOCK_RATE_GET, SCMI_COMMAND, proto->id, 0x0); msg.len = sizeof(clk_id); msg.content = &clk_id; reply.hdr = msg.hdr; reply.len = sizeof(reply_buffer); reply.content = &reply_buffer; ret = scmi_send_message(proto, &msg, &reply); if (ret < 0) { return ret; } if (reply_buffer.status != SCMI_SUCCESS) { return scmi_status_to_errno(reply_buffer.status); } *rate = reply_buffer.rate[0]; return 0; } int scmi_clock_config_set(struct scmi_protocol *proto, struct scmi_clock_config *cfg) { struct scmi_message msg, reply; int status, ret; /* sanity checks */ if (!proto || !cfg) { return -EINVAL; } if (proto->id != SCMI_PROTOCOL_CLOCK) { return -EINVAL; } /* extended attributes currently not supported */ if (cfg->attributes & SCMI_CLK_CONFIG_EA_MASK) { return -ENOTSUP; } /* invalid because extended attributes are not supported */ if (SCMI_CLK_CONFIG_ENABLE_DISABLE(cfg->attributes) == 3) { return -ENOTSUP; } /* this is a reserved value */ if (SCMI_CLK_CONFIG_ENABLE_DISABLE(cfg->attributes) == 2) { return -EINVAL; } msg.hdr = SCMI_MESSAGE_HDR_MAKE(SCMI_CLK_MSG_CLOCK_CONFIG_SET, SCMI_COMMAND, proto->id, 0x0); msg.len = sizeof(*cfg); msg.content = cfg; reply.hdr = msg.hdr; reply.len = sizeof(status); reply.content = &status; ret = scmi_send_message(proto, &msg, &reply); if (ret < 0) { return ret; } if (status != SCMI_SUCCESS) { return scmi_status_to_errno(status); } return 0; } int scmi_clock_protocol_attributes(struct scmi_protocol *proto, uint32_t *attributes) { struct scmi_message msg, reply; struct scmi_clock_attributes_reply reply_buffer; int ret; /* sanity checks */ if (!proto || !attributes) { return -EINVAL; } if (proto->id != SCMI_PROTOCOL_CLOCK) { return -EINVAL; } msg.hdr = SCMI_MESSAGE_HDR_MAKE(SCMI_CLK_MSG_PROTOCOL_ATTRIBUTES, SCMI_COMMAND, proto->id, 0x0); /* command has no parameters */ msg.len = 0x0; msg.content = NULL; reply.hdr = msg.hdr; reply.len = sizeof(reply_buffer); reply.content = &reply_buffer; ret = scmi_send_message(proto, &msg, &reply); if (ret < 0) { return ret; } if (reply_buffer.status != 0) { return scmi_status_to_errno(reply_buffer.status); } *attributes = reply_buffer.attributes; return 0; }