// SPDX-License-Identifier: GPL-2.0
/*
* System Control and Management Interface (SCMI) Sensor Protocol
*
* Copyright (C) 2018-2022 ARM Ltd.
*/
#define pr_fmt(fmt) "SCMI Notifications SENSOR - " fmt
#include <linux/bitfield.h>
#include <linux/module.h>
#include <linux/scmi_protocol.h>
#include "protocols.h"
#include "notify.h"
/* Updated only after ALL the mandatory features for that version are merged */
#define SCMI_PROTOCOL_SUPPORTED_VERSION 0x30001
#define SCMI_MAX_NUM_SENSOR_AXIS 63
#define SCMIv2_SENSOR_PROTOCOL 0x10000
enum scmi_sensor_protocol_cmd {
SENSOR_DESCRIPTION_GET = 0x3,
SENSOR_TRIP_POINT_NOTIFY = 0x4,
SENSOR_TRIP_POINT_CONFIG = 0x5,
SENSOR_READING_GET = 0x6,
SENSOR_AXIS_DESCRIPTION_GET = 0x7,
SENSOR_LIST_UPDATE_INTERVALS = 0x8,
SENSOR_CONFIG_GET = 0x9,
SENSOR_CONFIG_SET = 0xA,
SENSOR_CONTINUOUS_UPDATE_NOTIFY = 0xB,
SENSOR_NAME_GET = 0xC,
SENSOR_AXIS_NAME_GET = 0xD,
};
struct scmi_msg_resp_sensor_attributes {
__le16 num_sensors;
u8 max_requests;
u8 reserved;
__le32 reg_addr_low;
__le32 reg_addr_high;
__le32 reg_size;
};
/* v3 attributes_low macros */
#define SUPPORTS_UPDATE_NOTIFY(x) FIELD_GET(BIT(30), (x))
#define SENSOR_TSTAMP_EXP(x) FIELD_GET(GENMASK(14, 10), (x))
#define SUPPORTS_TIMESTAMP(x) FIELD_GET(BIT(9), (x))
#define SUPPORTS_EXTEND_ATTRS(x) FIELD_GET(BIT(8), (x))
/* v2 attributes_high macros */
#define SENSOR_UPDATE_BASE(x) FIELD_GET(GENMASK(31, 27), (x))
#define SENSOR_UPDATE_SCALE(x) FIELD_GET(GENMASK(26, 22), (x))
/* v3 attributes_high macros */
#define SENSOR_AXIS_NUMBER(x) FIELD_GET(GENMASK(21, 16), (x))
#define SUPPORTS_AXIS(x) FIELD_GET(BIT(8), (x))
/* v3 resolution macros */
#define SENSOR_RES(x) FIELD_GET(GENMASK(26, 0), (x))
#define SENSOR_RES_EXP(x) FIELD_GET(GENMASK(31, 27), (x))
struct scmi_msg_resp_attrs {
__le32 min_range_low;
__le32 min_range_high;
__le32 max_range_low;
__le32 max_range_high;
};
struct scmi_msg_sensor_description {
__le32 desc_index;
};
struct scmi_msg_resp_sensor_description {
__le16 num_returned;
__le16 num_remaining;
struct scmi_sensor_descriptor {
__le32 id;
__le32 attributes_low;
/* Common attributes_low macros */
#define SUPPORTS_ASYNC_READ(x) FIELD_GET(BIT(31), (x))
#define SUPPORTS_EXTENDED_NAMES(x) FIELD_GET(BIT(29), (x))
#define NUM_TRIP_POINTS(x) FIELD_GET(GENMASK(7, 0), (x))
__le32 attributes_high;
/* Common attributes_high macros */
#define SENSOR_SCALE(x) FIELD_GET(GENMASK(15, 11), (x))
#define SENSOR_SCALE_SIGN BIT(4)
#define SENSOR_SCALE_EXTEND GENMASK(31, 5)
#define SENSOR_TYPE(x) FIELD_GET(GENMASK(7, 0), (x))
u8 name[SCMI_SHORT_NAME_MAX_SIZE];
/* only for version > 2.0 */
__le32 power;
__le32 resolution;
struct scmi_msg_resp_attrs scalar_attrs;
} desc[];
};
/* Base scmi_sensor_descriptor size excluding extended attrs after name */
#define SCMI_MSG_RESP_SENS_DESCR_BASE_SZ 28
/* Sign extend to a full s32 */
#define S32_EXT(v) \
({ \
int __v = (v); \
\
if (__v & SENSOR_SCALE_SIGN) \
__v |= SENSOR_SCALE_EXTEND; \
__v; \
})
struct scmi_msg_sensor_axis_description_get {
__le32 id;
__le32 axis_desc_index;
};
struct scmi_msg_resp_sensor_axis_description {
__le32 num_axis_flags;
#define NUM_AXIS_RETURNED(x) FIELD_GET(GENMASK(5, 0), (x))
#define NUM_AXIS_REMAINING(x) FIELD_GET(GENMASK(31, 26), (x))
struct scmi_axis_descriptor {
__le32 id;
__le32 attributes_low;
#define SUPPORTS_EXTENDED_AXIS_NAMES(x) FIELD_GET(BIT(9), (x))
__le32 attributes_high;
u8 name[SCMI_SHORT_NAME_MAX_SIZE];
__le32 resolution;
struct scmi_msg_resp_attrs attrs;
} desc[];
};
struct scmi_msg_resp_sensor_axis_names_description {
__le32 num_axis_flags;
struct scmi_sensor_axis_name_descriptor {
__le32 axis_id;
u8 name[SCMI_MAX_STR_SIZE];
} desc[];
};
/* Base scmi_axis_descriptor size excluding extended attrs after name */
#define SCMI_MSG_RESP_AXIS_DESCR_BASE_SZ 28
struct scmi_msg_sensor_list_update_intervals {
__le32 id;
__le32 index;
};
struct scmi_msg_resp_sensor_list_update_intervals {
__le32 num_intervals_flags;
#define NUM_INTERVALS_RETURNED(x) FIELD_GET(GENMASK(11, 0), (x))
#define SEGMENTED_INTVL_FORMAT(x) FIELD_GET(BIT(12), (x))
#define NUM_INTERVALS_REMAINING(x) FIELD_GET(GENMASK(31, 16), (x))
__le32 intervals[];
};
struct scmi_msg_sensor_request_notify {
__le32 id;
__le32 event_control;
#define SENSOR_NOTIFY_ALL BIT(0)
};
struct scmi_msg_set_sensor_trip_point {
__le32 id;
__le32 event_control;
#define SENSOR_TP_EVENT_MASK (0x3)
#define SENSOR_TP_DISABLED 0x0
#define SENSOR_TP_POSITIVE 0x1
#define SENSOR_TP_NEGATIVE 0x2
#define SENSOR_TP_BOTH 0x3
#define SENSOR_TP_ID(x) (((x) & 0xff) << 4)
__le32 value_low;
__le32 value_high;
};
struct scmi_msg_sensor_config_set {
__le32 id;
__le32 sensor_config;
};
struct scmi_msg_sensor_reading_get {
__le32 id;
__le32 flags;
#define SENSOR_READ_ASYNC BIT(0)
};
struct scmi_resp_sensor_reading_complete {
__le32 id;
__le32 readings_low;
__le32 readings_high;
};
struct scmi_sensor_reading_resp {
__le32 sensor_value_low;
__le32 sensor_value_high;
__le32 timestamp_low;
__le32 timestamp_high;
};
struct scmi_resp_sensor_reading_complete_v3 {
__le32 id;
struct scmi_sensor_reading_resp readings[];
};
struct scmi_sensor_trip_notify_payld {
__le32 agent_id;
__le32 sensor_id;
__le32 trip_point_desc;
};
struct scmi_sensor_update_notify_payld {
__le32 agent_id;
__le32 sensor_id;
struct scmi_sensor_reading_resp readings[];
};
struct sensors_info {
u32 version;
bool notify_trip_point_cmd;
bool notify_continuos_update_cmd;
int num_sensors;
int max_requests;
u64 reg_addr;
u32 reg_size;
struct scmi_sensor_info *sensors;
};