You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
277 lines
7.1 KiB
277 lines
7.1 KiB
// SPDX-License-Identifier: BSD-3-Clause
|
|
/*
|
|
* Copyright 2021-2024 NXP
|
|
*/
|
|
|
|
#include <cdefs.h>
|
|
#include <string.h>
|
|
|
|
#include "common.h"
|
|
|
|
#include <drivers/scmi-msg.h>
|
|
#include <drivers/scmi.h>
|
|
#include <lib/utils_def.h>
|
|
|
|
static bool message_id_is_supported(size_t message_id);
|
|
|
|
uint16_t plat_scmi_sensor_count(unsigned int agent_id __unused)
|
|
{
|
|
if (sensor_ops.sensor_count != NULL) {
|
|
return sensor_ops.sensor_count(agent_id);
|
|
}
|
|
|
|
return 0U;
|
|
}
|
|
|
|
uint8_t plat_scmi_sensor_max_requests(unsigned int agent_id __unused)
|
|
{
|
|
if (sensor_ops.sensor_max_request != NULL) {
|
|
return sensor_ops.sensor_max_request(agent_id);
|
|
}
|
|
|
|
return 0U;
|
|
}
|
|
|
|
uint32_t plat_scmi_sensor_reg(unsigned int agent_id __unused,
|
|
unsigned int *addr)
|
|
{
|
|
if (sensor_ops.get_sensor_req != NULL) {
|
|
return sensor_ops.get_sensor_req(agent_id, addr);
|
|
}
|
|
|
|
return 0U;
|
|
}
|
|
|
|
int32_t plat_scmi_sensor_reading_get(uint32_t agent_id __unused,
|
|
uint16_t sensor_id __unused,
|
|
uint32_t *val __unused)
|
|
{
|
|
if (sensor_ops.sensor_reading_get != NULL) {
|
|
return sensor_ops.sensor_reading_get(agent_id, sensor_id, val);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
uint32_t plat_scmi_sensor_description_get(uint32_t agent_id __unused,
|
|
uint16_t desc_index __unused,
|
|
struct scmi_sensor_desc *desc __unused)
|
|
{
|
|
if (sensor_ops.sensor_description_get != NULL) {
|
|
return sensor_ops.sensor_description_get(agent_id, desc_index, desc);
|
|
}
|
|
|
|
return 0U;
|
|
}
|
|
|
|
uint32_t plat_scmi_sensor_update_interval(uint32_t agent_id __unused,
|
|
uint16_t sensor_id __unused)
|
|
{
|
|
if (sensor_ops.sensor_update_interval != NULL) {
|
|
return sensor_ops.sensor_update_interval(agent_id, sensor_id);
|
|
}
|
|
|
|
return 0U;
|
|
}
|
|
|
|
uint32_t plat_scmi_sensor_state(uint32_t agent_id __unused,
|
|
uint16_t sensor_id __unused)
|
|
{
|
|
if (sensor_ops.sensor_state != NULL) {
|
|
return sensor_ops.sensor_state(agent_id, sensor_id);
|
|
}
|
|
|
|
return 0U;
|
|
}
|
|
|
|
uint32_t plat_scmi_sensor_timestamped(uint32_t agent_id __unused,
|
|
uint16_t sensor_id __unused)
|
|
{
|
|
if (sensor_ops.sensor_timestamped != NULL) {
|
|
return sensor_ops.sensor_timestamped(agent_id, sensor_id);
|
|
}
|
|
|
|
return 0U;
|
|
}
|
|
|
|
static void report_version(struct scmi_msg *msg)
|
|
{
|
|
struct scmi_protocol_version_p2a return_values = {
|
|
.status = SCMI_SUCCESS,
|
|
.version = SCMI_PROTOCOL_VERSION_SENSOR,
|
|
};
|
|
|
|
if (msg->in_size != 0U) {
|
|
scmi_status_response(msg, SCMI_PROTOCOL_ERROR);
|
|
return;
|
|
}
|
|
|
|
scmi_write_response(msg, &return_values, sizeof(return_values));
|
|
}
|
|
|
|
static void report_attributes(struct scmi_msg *msg)
|
|
{
|
|
unsigned int addr[2];
|
|
unsigned int len;
|
|
|
|
struct scmi_protocol_attributes_p2a_sensor return_values = {
|
|
.status = SCMI_SUCCESS,
|
|
};
|
|
|
|
if (msg->in_size != 0U) {
|
|
scmi_status_response(msg, SCMI_PROTOCOL_ERROR);
|
|
return;
|
|
}
|
|
|
|
return_values.num_sensors = plat_scmi_sensor_count(msg->agent_id);
|
|
return_values.max_reqs = plat_scmi_sensor_max_requests(msg->agent_id);
|
|
len = plat_scmi_sensor_reg(msg->agent_id, addr);
|
|
if (len != 0U) {
|
|
return_values.sensor_reg_low = addr[0];
|
|
return_values.sensor_reg_high = addr[1];
|
|
return_values.sensor_reg_len = len;
|
|
}
|
|
|
|
scmi_write_response(msg, &return_values, sizeof(return_values));
|
|
}
|
|
|
|
static void report_message_attributes(struct scmi_msg *msg)
|
|
{
|
|
struct scmi_protocol_message_attributes_a2p *in_args = (void *)msg->in;
|
|
struct scmi_protocol_message_attributes_p2a return_values = {
|
|
.status = SCMI_SUCCESS,
|
|
/* For this protocol, attributes shall be zero */
|
|
.attributes = 0U,
|
|
};
|
|
|
|
if (msg->in_size != sizeof(*in_args)) {
|
|
scmi_status_response(msg, SCMI_PROTOCOL_ERROR);
|
|
return;
|
|
}
|
|
|
|
if (!message_id_is_supported(in_args->message_id)) {
|
|
scmi_status_response(msg, SCMI_NOT_FOUND);
|
|
return;
|
|
}
|
|
|
|
scmi_write_response(msg, &return_values, sizeof(return_values));
|
|
}
|
|
|
|
static void scmi_sensor_description_get(struct scmi_msg *msg)
|
|
{
|
|
const struct scmi_sensor_description_get_a2p *in_args = (void *)msg->in;
|
|
struct scmi_sensor_description_get_p2a return_values = {
|
|
.status = SCMI_SUCCESS,
|
|
};
|
|
struct scmi_sensor_desc desc;
|
|
unsigned int desc_index = 0U;
|
|
unsigned int num_sensor_flags;
|
|
|
|
if (msg->in_size != sizeof(*in_args)) {
|
|
scmi_status_response(msg, SCMI_PROTOCOL_ERROR);
|
|
return;
|
|
}
|
|
|
|
desc_index = SPECULATION_SAFE_VALUE(in_args->desc_index);
|
|
|
|
num_sensor_flags = plat_scmi_sensor_description_get(msg->agent_id, desc_index,
|
|
&desc);
|
|
return_values.num_sensor_flags = num_sensor_flags;
|
|
|
|
memcpy(msg->out, &return_values, sizeof(return_values));
|
|
memcpy(msg->out + sizeof(return_values), &desc, sizeof(desc));
|
|
msg->out_size_out = sizeof(return_values) + sizeof(struct scmi_sensor_desc);
|
|
}
|
|
|
|
static void scmi_sensor_config_get(struct scmi_msg *msg)
|
|
{
|
|
const struct scmi_sensor_config_get_a2p *in_args = (void *)msg->in;
|
|
struct scmi_sensor_config_get_p2a return_values = {
|
|
.status = SCMI_SUCCESS,
|
|
};
|
|
unsigned int sensor_id = 0U;
|
|
uint32_t update_interval, state, timestamped;
|
|
|
|
if (msg->in_size != sizeof(*in_args)) {
|
|
scmi_status_response(msg, SCMI_PROTOCOL_ERROR);
|
|
return;
|
|
}
|
|
|
|
sensor_id = SPECULATION_SAFE_VALUE(in_args->sensor_id);
|
|
|
|
if (sensor_id >= plat_scmi_sensor_count(msg->agent_id)) {
|
|
scmi_status_response(msg, SCMI_INVALID_PARAMETERS);
|
|
return;
|
|
}
|
|
|
|
update_interval = plat_scmi_sensor_update_interval(msg->agent_id, sensor_id);
|
|
state = plat_scmi_sensor_state(msg->agent_id, sensor_id);
|
|
timestamped = plat_scmi_sensor_timestamped(msg->agent_id, sensor_id);
|
|
return_values.sensor_config = (update_interval << 11) | (timestamped << 1) | state;
|
|
|
|
scmi_write_response(msg, &return_values, sizeof(return_values));
|
|
}
|
|
|
|
static void scmi_sensor_reading_get(struct scmi_msg *msg)
|
|
{
|
|
const struct scmi_sensor_reading_get_a2p *in_args = (void *)msg->in;
|
|
struct scmi_sensor_reading_get_p2a return_values = {
|
|
.status = SCMI_SUCCESS,
|
|
};
|
|
unsigned int sensor_id = 0U;
|
|
int32_t ret;
|
|
|
|
if (msg->in_size != sizeof(*in_args)) {
|
|
scmi_status_response(msg, SCMI_PROTOCOL_ERROR);
|
|
return;
|
|
}
|
|
|
|
sensor_id = SPECULATION_SAFE_VALUE(in_args->sensor_id);
|
|
|
|
if (sensor_id >= plat_scmi_sensor_count(msg->agent_id)) {
|
|
scmi_status_response(msg, SCMI_INVALID_PARAMETERS);
|
|
return;
|
|
}
|
|
|
|
ret = plat_scmi_sensor_reading_get(msg->agent_id, sensor_id,
|
|
(uint32_t *)&return_values.val);
|
|
if (ret) {
|
|
scmi_status_response(msg, SCMI_HARDWARE_ERROR);
|
|
return;
|
|
}
|
|
|
|
scmi_write_response(msg, &return_values, sizeof(return_values));
|
|
}
|
|
|
|
static void scmi_sensor_list_update_intervals(struct scmi_msg *msg)
|
|
{
|
|
/* TODO */
|
|
scmi_status_response(msg, SCMI_NOT_SUPPORTED);
|
|
}
|
|
|
|
static const scmi_msg_handler_t scmi_sensor_handler_table[SCMI_SENSOR_MAX] = {
|
|
[SCMI_PROTOCOL_VERSION] = report_version,
|
|
[SCMI_PROTOCOL_ATTRIBUTES] = report_attributes,
|
|
[SCMI_PROTOCOL_MESSAGE_ATTRIBUTES] = report_message_attributes,
|
|
[SCMI_SENSOR_DESCRIPTION_GET] = scmi_sensor_description_get,
|
|
[SCMI_SENSOR_CONFIG_GET] = scmi_sensor_config_get,
|
|
[SCMI_SENSOR_LIST_UPDATE_INTERVALS] = scmi_sensor_list_update_intervals,
|
|
[SCMI_SENSOR_READING_GET] = scmi_sensor_reading_get,
|
|
};
|
|
|
|
static bool message_id_is_supported(size_t message_id)
|
|
{
|
|
return scmi_sensor_handler_table[message_id] != NULL;
|
|
}
|
|
|
|
scmi_msg_handler_t scmi_msg_get_sensor_handler(struct scmi_msg *msg)
|
|
{
|
|
unsigned int message_id = SPECULATION_SAFE_VALUE(msg->message_id);
|
|
|
|
if (!message_id_is_supported(message_id)) {
|
|
VERBOSE("pd handle not found %u\n", msg->message_id);
|
|
return NULL;
|
|
}
|
|
|
|
return scmi_sensor_handler_table[message_id];
|
|
}
|
|
|