Linux Audio

Check our new training course

Loading...
Note: File does not exist in v3.1.
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 * System Control and Management Interface (SCMI) Sensor Protocol
   4 *
   5 * Copyright (C) 2018-2022 ARM Ltd.
   6 */
   7
   8#define pr_fmt(fmt) "SCMI Notifications SENSOR - " fmt
   9
  10#include <linux/bitfield.h>
  11#include <linux/module.h>
  12#include <linux/scmi_protocol.h>
  13
  14#include "protocols.h"
  15#include "notify.h"
  16
  17/* Updated only after ALL the mandatory features for that version are merged */
  18#define SCMI_PROTOCOL_SUPPORTED_VERSION		0x30001
  19
  20#define SCMI_MAX_NUM_SENSOR_AXIS	63
  21#define	SCMIv2_SENSOR_PROTOCOL		0x10000
  22
  23enum scmi_sensor_protocol_cmd {
  24	SENSOR_DESCRIPTION_GET = 0x3,
  25	SENSOR_TRIP_POINT_NOTIFY = 0x4,
  26	SENSOR_TRIP_POINT_CONFIG = 0x5,
  27	SENSOR_READING_GET = 0x6,
  28	SENSOR_AXIS_DESCRIPTION_GET = 0x7,
  29	SENSOR_LIST_UPDATE_INTERVALS = 0x8,
  30	SENSOR_CONFIG_GET = 0x9,
  31	SENSOR_CONFIG_SET = 0xA,
  32	SENSOR_CONTINUOUS_UPDATE_NOTIFY = 0xB,
  33	SENSOR_NAME_GET = 0xC,
  34	SENSOR_AXIS_NAME_GET = 0xD,
  35};
  36
  37struct scmi_msg_resp_sensor_attributes {
  38	__le16 num_sensors;
  39	u8 max_requests;
  40	u8 reserved;
  41	__le32 reg_addr_low;
  42	__le32 reg_addr_high;
  43	__le32 reg_size;
  44};
  45
  46/* v3 attributes_low macros */
  47#define SUPPORTS_UPDATE_NOTIFY(x)	FIELD_GET(BIT(30), (x))
  48#define SENSOR_TSTAMP_EXP(x)		FIELD_GET(GENMASK(14, 10), (x))
  49#define SUPPORTS_TIMESTAMP(x)		FIELD_GET(BIT(9), (x))
  50#define SUPPORTS_EXTEND_ATTRS(x)	FIELD_GET(BIT(8), (x))
  51
  52/* v2 attributes_high macros */
  53#define SENSOR_UPDATE_BASE(x)		FIELD_GET(GENMASK(31, 27), (x))
  54#define SENSOR_UPDATE_SCALE(x)		FIELD_GET(GENMASK(26, 22), (x))
  55
  56/* v3 attributes_high macros */
  57#define SENSOR_AXIS_NUMBER(x)		FIELD_GET(GENMASK(21, 16), (x))
  58#define SUPPORTS_AXIS(x)		FIELD_GET(BIT(8), (x))
  59
  60/* v3 resolution macros */
  61#define SENSOR_RES(x)			FIELD_GET(GENMASK(26, 0), (x))
  62#define SENSOR_RES_EXP(x)		FIELD_GET(GENMASK(31, 27), (x))
  63
  64struct scmi_msg_resp_attrs {
  65	__le32 min_range_low;
  66	__le32 min_range_high;
  67	__le32 max_range_low;
  68	__le32 max_range_high;
  69};
  70
  71struct scmi_msg_sensor_description {
  72	__le32 desc_index;
  73};
  74
  75struct scmi_msg_resp_sensor_description {
  76	__le16 num_returned;
  77	__le16 num_remaining;
  78	struct scmi_sensor_descriptor {
  79		__le32 id;
  80		__le32 attributes_low;
  81/* Common attributes_low macros */
  82#define SUPPORTS_ASYNC_READ(x)		FIELD_GET(BIT(31), (x))
  83#define SUPPORTS_EXTENDED_NAMES(x)	FIELD_GET(BIT(29), (x))
  84#define NUM_TRIP_POINTS(x)		FIELD_GET(GENMASK(7, 0), (x))
  85		__le32 attributes_high;
  86/* Common attributes_high macros */
  87#define SENSOR_SCALE(x)			FIELD_GET(GENMASK(15, 11), (x))
  88#define SENSOR_SCALE_SIGN		BIT(4)
  89#define SENSOR_SCALE_EXTEND		GENMASK(31, 5)
  90#define SENSOR_TYPE(x)			FIELD_GET(GENMASK(7, 0), (x))
  91		u8 name[SCMI_SHORT_NAME_MAX_SIZE];
  92		/* only for version > 2.0 */
  93		__le32 power;
  94		__le32 resolution;
  95		struct scmi_msg_resp_attrs scalar_attrs;
  96	} desc[];
  97};
  98
  99/* Base scmi_sensor_descriptor size excluding extended attrs after name */
 100#define SCMI_MSG_RESP_SENS_DESCR_BASE_SZ	28
 101
 102/* Sign extend to a full s32 */
 103#define	S32_EXT(v)							\
 104	({								\
 105		int __v = (v);						\
 106									\
 107		if (__v & SENSOR_SCALE_SIGN)				\
 108			__v |= SENSOR_SCALE_EXTEND;			\
 109		__v;							\
 110	})
 111
 112struct scmi_msg_sensor_axis_description_get {
 113	__le32 id;
 114	__le32 axis_desc_index;
 115};
 116
 117struct scmi_msg_resp_sensor_axis_description {
 118	__le32 num_axis_flags;
 119#define NUM_AXIS_RETURNED(x)		FIELD_GET(GENMASK(5, 0), (x))
 120#define NUM_AXIS_REMAINING(x)		FIELD_GET(GENMASK(31, 26), (x))
 121	struct scmi_axis_descriptor {
 122		__le32 id;
 123		__le32 attributes_low;
 124#define SUPPORTS_EXTENDED_AXIS_NAMES(x)	FIELD_GET(BIT(9), (x))
 125		__le32 attributes_high;
 126		u8 name[SCMI_SHORT_NAME_MAX_SIZE];
 127		__le32 resolution;
 128		struct scmi_msg_resp_attrs attrs;
 129	} desc[];
 130};
 131
 132struct scmi_msg_resp_sensor_axis_names_description {
 133	__le32 num_axis_flags;
 134	struct scmi_sensor_axis_name_descriptor {
 135		__le32 axis_id;
 136		u8 name[SCMI_MAX_STR_SIZE];
 137	} desc[];
 138};
 139
 140/* Base scmi_axis_descriptor size excluding extended attrs after name */
 141#define SCMI_MSG_RESP_AXIS_DESCR_BASE_SZ	28
 142
 143struct scmi_msg_sensor_list_update_intervals {
 144	__le32 id;
 145	__le32 index;
 146};
 147
 148struct scmi_msg_resp_sensor_list_update_intervals {
 149	__le32 num_intervals_flags;
 150#define NUM_INTERVALS_RETURNED(x)	FIELD_GET(GENMASK(11, 0), (x))
 151#define SEGMENTED_INTVL_FORMAT(x)	FIELD_GET(BIT(12), (x))
 152#define NUM_INTERVALS_REMAINING(x)	FIELD_GET(GENMASK(31, 16), (x))
 153	__le32 intervals[];
 154};
 155
 156struct scmi_msg_sensor_request_notify {
 157	__le32 id;
 158	__le32 event_control;
 159#define SENSOR_NOTIFY_ALL	BIT(0)
 160};
 161
 162struct scmi_msg_set_sensor_trip_point {
 163	__le32 id;
 164	__le32 event_control;
 165#define SENSOR_TP_EVENT_MASK	(0x3)
 166#define SENSOR_TP_DISABLED	0x0
 167#define SENSOR_TP_POSITIVE	0x1
 168#define SENSOR_TP_NEGATIVE	0x2
 169#define SENSOR_TP_BOTH		0x3
 170#define SENSOR_TP_ID(x)		(((x) & 0xff) << 4)
 171	__le32 value_low;
 172	__le32 value_high;
 173};
 174
 175struct scmi_msg_sensor_config_set {
 176	__le32 id;
 177	__le32 sensor_config;
 178};
 179
 180struct scmi_msg_sensor_reading_get {
 181	__le32 id;
 182	__le32 flags;
 183#define SENSOR_READ_ASYNC	BIT(0)
 184};
 185
 186struct scmi_resp_sensor_reading_complete {
 187	__le32 id;
 188	__le32 readings_low;
 189	__le32 readings_high;
 190};
 191
 192struct scmi_sensor_reading_resp {
 193	__le32 sensor_value_low;
 194	__le32 sensor_value_high;
 195	__le32 timestamp_low;
 196	__le32 timestamp_high;
 197};
 198
 199struct scmi_resp_sensor_reading_complete_v3 {
 200	__le32 id;
 201	struct scmi_sensor_reading_resp readings[];
 202};
 203
 204struct scmi_sensor_trip_notify_payld {
 205	__le32 agent_id;
 206	__le32 sensor_id;
 207	__le32 trip_point_desc;
 208};
 209
 210struct scmi_sensor_update_notify_payld {
 211	__le32 agent_id;
 212	__le32 sensor_id;
 213	struct scmi_sensor_reading_resp readings[];
 214};
 215
 216struct sensors_info {
 217	u32 version;
 218	bool notify_trip_point_cmd;
 219	bool notify_continuos_update_cmd;
 220	int num_sensors;
 221	int max_requests;
 222	u64 reg_addr;
 223	u32 reg_size;
 224	struct scmi_sensor_info *sensors;
 225};
 226
 227static int scmi_sensor_attributes_get(const struct scmi_protocol_handle *ph,
 228				      struct sensors_info *si)
 229{
 230	int ret;
 231	struct scmi_xfer *t;
 232	struct scmi_msg_resp_sensor_attributes *attr;
 233
 234	ret = ph->xops->xfer_get_init(ph, PROTOCOL_ATTRIBUTES,
 235				      0, sizeof(*attr), &t);
 236	if (ret)
 237		return ret;
 238
 239	attr = t->rx.buf;
 240
 241	ret = ph->xops->do_xfer(ph, t);
 242	if (!ret) {
 243		si->num_sensors = le16_to_cpu(attr->num_sensors);
 244		si->max_requests = attr->max_requests;
 245		si->reg_addr = le32_to_cpu(attr->reg_addr_low) |
 246				(u64)le32_to_cpu(attr->reg_addr_high) << 32;
 247		si->reg_size = le32_to_cpu(attr->reg_size);
 248	}
 249
 250	ph->xops->xfer_put(ph, t);
 251
 252	if (!ret) {
 253		if (!ph->hops->protocol_msg_check(ph,
 254						  SENSOR_TRIP_POINT_NOTIFY, NULL))
 255			si->notify_trip_point_cmd = true;
 256
 257		if (!ph->hops->protocol_msg_check(ph,
 258						  SENSOR_CONTINUOUS_UPDATE_NOTIFY,
 259						  NULL))
 260			si->notify_continuos_update_cmd = true;
 261	}
 262
 263	return ret;
 264}
 265
 266static inline void scmi_parse_range_attrs(struct scmi_range_attrs *out,
 267					  const struct scmi_msg_resp_attrs *in)
 268{
 269	out->min_range = get_unaligned_le64((void *)&in->min_range_low);
 270	out->max_range = get_unaligned_le64((void *)&in->max_range_low);
 271}
 272
 273struct scmi_sens_ipriv {
 274	void *priv;
 275	struct device *dev;
 276};
 277
 278static void iter_intervals_prepare_message(void *message,
 279					   unsigned int desc_index,
 280					   const void *p)
 281{
 282	struct scmi_msg_sensor_list_update_intervals *msg = message;
 283	const struct scmi_sensor_info *s;
 284
 285	s = ((const struct scmi_sens_ipriv *)p)->priv;
 286	/* Set the number of sensors to be skipped/already read */
 287	msg->id = cpu_to_le32(s->id);
 288	msg->index = cpu_to_le32(desc_index);
 289}
 290
 291static int iter_intervals_update_state(struct scmi_iterator_state *st,
 292				       const void *response, void *p)
 293{
 294	u32 flags;
 295	struct scmi_sensor_info *s = ((struct scmi_sens_ipriv *)p)->priv;
 296	struct device *dev = ((struct scmi_sens_ipriv *)p)->dev;
 297	const struct scmi_msg_resp_sensor_list_update_intervals *r = response;
 298
 299	flags = le32_to_cpu(r->num_intervals_flags);
 300	st->num_returned = NUM_INTERVALS_RETURNED(flags);
 301	st->num_remaining = NUM_INTERVALS_REMAINING(flags);
 302
 303	/*
 304	 * Max intervals is not declared previously anywhere so we
 305	 * assume it's returned+remaining on first call.
 306	 */
 307	if (!st->max_resources) {
 308		s->intervals.segmented = SEGMENTED_INTVL_FORMAT(flags);
 309		s->intervals.count = st->num_returned + st->num_remaining;
 310		/* segmented intervals are reported in one triplet */
 311		if (s->intervals.segmented &&
 312		    (st->num_remaining || st->num_returned != 3)) {
 313			dev_err(dev,
 314				"Sensor ID:%d advertises an invalid segmented interval (%d)\n",
 315				s->id, s->intervals.count);
 316			s->intervals.segmented = false;
 317			s->intervals.count = 0;
 318			return -EINVAL;
 319		}
 320		/* Direct allocation when exceeding pre-allocated */
 321		if (s->intervals.count >= SCMI_MAX_PREALLOC_POOL) {
 322			s->intervals.desc =
 323				devm_kcalloc(dev,
 324					     s->intervals.count,
 325					     sizeof(*s->intervals.desc),
 326					     GFP_KERNEL);
 327			if (!s->intervals.desc) {
 328				s->intervals.segmented = false;
 329				s->intervals.count = 0;
 330				return -ENOMEM;
 331			}
 332		}
 333
 334		st->max_resources = s->intervals.count;
 335	}
 336
 337	return 0;
 338}
 339
 340static int
 341iter_intervals_process_response(const struct scmi_protocol_handle *ph,
 342				const void *response,
 343				struct scmi_iterator_state *st, void *p)
 344{
 345	const struct scmi_msg_resp_sensor_list_update_intervals *r = response;
 346	struct scmi_sensor_info *s = ((struct scmi_sens_ipriv *)p)->priv;
 347
 348	s->intervals.desc[st->desc_index + st->loop_idx] =
 349		le32_to_cpu(r->intervals[st->loop_idx]);
 350
 351	return 0;
 352}
 353
 354static int scmi_sensor_update_intervals(const struct scmi_protocol_handle *ph,
 355					struct scmi_sensor_info *s)
 356{
 357	void *iter;
 358	struct scmi_iterator_ops ops = {
 359		.prepare_message = iter_intervals_prepare_message,
 360		.update_state = iter_intervals_update_state,
 361		.process_response = iter_intervals_process_response,
 362	};
 363	struct scmi_sens_ipriv upriv = {
 364		.priv = s,
 365		.dev = ph->dev,
 366	};
 367
 368	iter = ph->hops->iter_response_init(ph, &ops, s->intervals.count,
 369					    SENSOR_LIST_UPDATE_INTERVALS,
 370					    sizeof(struct scmi_msg_sensor_list_update_intervals),
 371					    &upriv);
 372	if (IS_ERR(iter))
 373		return PTR_ERR(iter);
 374
 375	return ph->hops->iter_response_run(iter);
 376}
 377
 378struct scmi_apriv {
 379	bool any_axes_support_extended_names;
 380	struct scmi_sensor_info *s;
 381};
 382
 383static void iter_axes_desc_prepare_message(void *message,
 384					   const unsigned int desc_index,
 385					   const void *priv)
 386{
 387	struct scmi_msg_sensor_axis_description_get *msg = message;
 388	const struct scmi_apriv *apriv = priv;
 389
 390	/* Set the number of sensors to be skipped/already read */
 391	msg->id = cpu_to_le32(apriv->s->id);
 392	msg->axis_desc_index = cpu_to_le32(desc_index);
 393}
 394
 395static int
 396iter_axes_desc_update_state(struct scmi_iterator_state *st,
 397			    const void *response, void *priv)
 398{
 399	u32 flags;
 400	const struct scmi_msg_resp_sensor_axis_description *r = response;
 401
 402	flags = le32_to_cpu(r->num_axis_flags);
 403	st->num_returned = NUM_AXIS_RETURNED(flags);
 404	st->num_remaining = NUM_AXIS_REMAINING(flags);
 405	st->priv = (void *)&r->desc[0];
 406
 407	return 0;
 408}
 409
 410static int
 411iter_axes_desc_process_response(const struct scmi_protocol_handle *ph,
 412				const void *response,
 413				struct scmi_iterator_state *st, void *priv)
 414{
 415	u32 attrh, attrl;
 416	struct scmi_sensor_axis_info *a;
 417	size_t dsize = SCMI_MSG_RESP_AXIS_DESCR_BASE_SZ;
 418	struct scmi_apriv *apriv = priv;
 419	const struct scmi_axis_descriptor *adesc = st->priv;
 420
 421	attrl = le32_to_cpu(adesc->attributes_low);
 422	if (SUPPORTS_EXTENDED_AXIS_NAMES(attrl))
 423		apriv->any_axes_support_extended_names = true;
 424
 425	a = &apriv->s->axis[st->desc_index + st->loop_idx];
 426	a->id = le32_to_cpu(adesc->id);
 427	a->extended_attrs = SUPPORTS_EXTEND_ATTRS(attrl);
 428
 429	attrh = le32_to_cpu(adesc->attributes_high);
 430	a->scale = S32_EXT(SENSOR_SCALE(attrh));
 431	a->type = SENSOR_TYPE(attrh);
 432	strscpy(a->name, adesc->name, SCMI_SHORT_NAME_MAX_SIZE);
 433
 434	if (a->extended_attrs) {
 435		unsigned int ares = le32_to_cpu(adesc->resolution);
 436
 437		a->resolution = SENSOR_RES(ares);
 438		a->exponent = S32_EXT(SENSOR_RES_EXP(ares));
 439		dsize += sizeof(adesc->resolution);
 440
 441		scmi_parse_range_attrs(&a->attrs, &adesc->attrs);
 442		dsize += sizeof(adesc->attrs);
 443	}
 444	st->priv = ((u8 *)adesc + dsize);
 445
 446	return 0;
 447}
 448
 449static int
 450iter_axes_extended_name_update_state(struct scmi_iterator_state *st,
 451				     const void *response, void *priv)
 452{
 453	u32 flags;
 454	const struct scmi_msg_resp_sensor_axis_names_description *r = response;
 455
 456	flags = le32_to_cpu(r->num_axis_flags);
 457	st->num_returned = NUM_AXIS_RETURNED(flags);
 458	st->num_remaining = NUM_AXIS_REMAINING(flags);
 459	st->priv = (void *)&r->desc[0];
 460
 461	return 0;
 462}
 463
 464static int
 465iter_axes_extended_name_process_response(const struct scmi_protocol_handle *ph,
 466					 const void *response,
 467					 struct scmi_iterator_state *st,
 468					 void *priv)
 469{
 470	struct scmi_sensor_axis_info *a;
 471	const struct scmi_apriv *apriv = priv;
 472	struct scmi_sensor_axis_name_descriptor *adesc = st->priv;
 473	u32 axis_id = le32_to_cpu(adesc->axis_id);
 474
 475	if (axis_id >= st->max_resources)
 476		return -EPROTO;
 477
 478	/*
 479	 * Pick the corresponding descriptor based on the axis_id embedded
 480	 * in the reply since the list of axes supporting extended names
 481	 * can be a subset of all the axes.
 482	 */
 483	a = &apriv->s->axis[axis_id];
 484	strscpy(a->name, adesc->name, SCMI_MAX_STR_SIZE);
 485	st->priv = ++adesc;
 486
 487	return 0;
 488}
 489
 490static int
 491scmi_sensor_axis_extended_names_get(const struct scmi_protocol_handle *ph,
 492				    struct scmi_sensor_info *s)
 493{
 494	int ret;
 495	void *iter;
 496	struct scmi_iterator_ops ops = {
 497		.prepare_message = iter_axes_desc_prepare_message,
 498		.update_state = iter_axes_extended_name_update_state,
 499		.process_response = iter_axes_extended_name_process_response,
 500	};
 501	struct scmi_apriv apriv = {
 502		.any_axes_support_extended_names = false,
 503		.s = s,
 504	};
 505
 506	iter = ph->hops->iter_response_init(ph, &ops, s->num_axis,
 507					    SENSOR_AXIS_NAME_GET,
 508					    sizeof(struct scmi_msg_sensor_axis_description_get),
 509					    &apriv);
 510	if (IS_ERR(iter))
 511		return PTR_ERR(iter);
 512
 513	/*
 514	 * Do not cause whole protocol initialization failure when failing to
 515	 * get extended names for axes.
 516	 */
 517	ret = ph->hops->iter_response_run(iter);
 518	if (ret)
 519		dev_warn(ph->dev,
 520			 "Failed to get axes extended names for %s (ret:%d).\n",
 521			 s->name, ret);
 522
 523	return 0;
 524}
 525
 526static int scmi_sensor_axis_description(const struct scmi_protocol_handle *ph,
 527					struct scmi_sensor_info *s,
 528					u32 version)
 529{
 530	int ret;
 531	void *iter;
 532	struct scmi_iterator_ops ops = {
 533		.prepare_message = iter_axes_desc_prepare_message,
 534		.update_state = iter_axes_desc_update_state,
 535		.process_response = iter_axes_desc_process_response,
 536	};
 537	struct scmi_apriv apriv = {
 538		.any_axes_support_extended_names = false,
 539		.s = s,
 540	};
 541
 542	s->axis = devm_kcalloc(ph->dev, s->num_axis,
 543			       sizeof(*s->axis), GFP_KERNEL);
 544	if (!s->axis)
 545		return -ENOMEM;
 546
 547	iter = ph->hops->iter_response_init(ph, &ops, s->num_axis,
 548					    SENSOR_AXIS_DESCRIPTION_GET,
 549					    sizeof(struct scmi_msg_sensor_axis_description_get),
 550					    &apriv);
 551	if (IS_ERR(iter))
 552		return PTR_ERR(iter);
 553
 554	ret = ph->hops->iter_response_run(iter);
 555	if (ret)
 556		return ret;
 557
 558	if (PROTOCOL_REV_MAJOR(version) >= 0x3 &&
 559	    apriv.any_axes_support_extended_names)
 560		ret = scmi_sensor_axis_extended_names_get(ph, s);
 561
 562	return ret;
 563}
 564
 565static void iter_sens_descr_prepare_message(void *message,
 566					    unsigned int desc_index,
 567					    const void *priv)
 568{
 569	struct scmi_msg_sensor_description *msg = message;
 570
 571	msg->desc_index = cpu_to_le32(desc_index);
 572}
 573
 574static int iter_sens_descr_update_state(struct scmi_iterator_state *st,
 575					const void *response, void *priv)
 576{
 577	const struct scmi_msg_resp_sensor_description *r = response;
 578
 579	st->num_returned = le16_to_cpu(r->num_returned);
 580	st->num_remaining = le16_to_cpu(r->num_remaining);
 581	st->priv = (void *)&r->desc[0];
 582
 583	return 0;
 584}
 585
 586static int
 587iter_sens_descr_process_response(const struct scmi_protocol_handle *ph,
 588				 const void *response,
 589				 struct scmi_iterator_state *st, void *priv)
 590
 591{
 592	int ret = 0;
 593	u32 attrh, attrl;
 594	size_t dsize = SCMI_MSG_RESP_SENS_DESCR_BASE_SZ;
 595	struct scmi_sensor_info *s;
 596	struct sensors_info *si = priv;
 597	const struct scmi_sensor_descriptor *sdesc = st->priv;
 598
 599	s = &si->sensors[st->desc_index + st->loop_idx];
 600	s->id = le32_to_cpu(sdesc->id);
 601
 602	attrl = le32_to_cpu(sdesc->attributes_low);
 603	/* common bitfields parsing */
 604	s->async = SUPPORTS_ASYNC_READ(attrl);
 605	s->num_trip_points = NUM_TRIP_POINTS(attrl);
 606	/**
 607	 * only SCMIv3.0 specific bitfield below.
 608	 * Such bitfields are assumed to be zeroed on non
 609	 * relevant fw versions...assuming fw not buggy !
 610	 */
 611	if (si->notify_continuos_update_cmd)
 612		s->update = SUPPORTS_UPDATE_NOTIFY(attrl);
 613	s->timestamped = SUPPORTS_TIMESTAMP(attrl);
 614	if (s->timestamped)
 615		s->tstamp_scale = S32_EXT(SENSOR_TSTAMP_EXP(attrl));
 616	s->extended_scalar_attrs = SUPPORTS_EXTEND_ATTRS(attrl);
 617
 618	attrh = le32_to_cpu(sdesc->attributes_high);
 619	/* common bitfields parsing */
 620	s->scale = S32_EXT(SENSOR_SCALE(attrh));
 621	s->type = SENSOR_TYPE(attrh);
 622	/* Use pre-allocated pool wherever possible */
 623	s->intervals.desc = s->intervals.prealloc_pool;
 624	if (si->version == SCMIv2_SENSOR_PROTOCOL) {
 625		s->intervals.segmented = false;
 626		s->intervals.count = 1;
 627		/*
 628		 * Convert SCMIv2.0 update interval format to
 629		 * SCMIv3.0 to be used as the common exposed
 630		 * descriptor, accessible via common macros.
 631		 */
 632		s->intervals.desc[0] = (SENSOR_UPDATE_BASE(attrh) << 5) |
 633					SENSOR_UPDATE_SCALE(attrh);
 634	} else {
 635		/*
 636		 * From SCMIv3.0 update intervals are retrieved
 637		 * via a dedicated (optional) command.
 638		 * Since the command is optional, on error carry
 639		 * on without any update interval.
 640		 */
 641		if (scmi_sensor_update_intervals(ph, s))
 642			dev_dbg(ph->dev,
 643				"Update Intervals not available for sensor ID:%d\n",
 644				s->id);
 645	}
 646	/**
 647	 * only > SCMIv2.0 specific bitfield below.
 648	 * Such bitfields are assumed to be zeroed on non
 649	 * relevant fw versions...assuming fw not buggy !
 650	 */
 651	s->num_axis = min_t(unsigned int,
 652			    SUPPORTS_AXIS(attrh) ?
 653			    SENSOR_AXIS_NUMBER(attrh) : 0,
 654			    SCMI_MAX_NUM_SENSOR_AXIS);
 655	strscpy(s->name, sdesc->name, SCMI_SHORT_NAME_MAX_SIZE);
 656
 657	/*
 658	 * If supported overwrite short name with the extended
 659	 * one; on error just carry on and use already provided
 660	 * short name.
 661	 */
 662	if (PROTOCOL_REV_MAJOR(si->version) >= 0x3 &&
 663	    SUPPORTS_EXTENDED_NAMES(attrl))
 664		ph->hops->extended_name_get(ph, SENSOR_NAME_GET, s->id,
 665					    NULL, s->name, SCMI_MAX_STR_SIZE);
 666
 667	if (s->extended_scalar_attrs) {
 668		s->sensor_power = le32_to_cpu(sdesc->power);
 669		dsize += sizeof(sdesc->power);
 670
 671		/* Only for sensors reporting scalar values */
 672		if (s->num_axis == 0) {
 673			unsigned int sres = le32_to_cpu(sdesc->resolution);
 674
 675			s->resolution = SENSOR_RES(sres);
 676			s->exponent = S32_EXT(SENSOR_RES_EXP(sres));
 677			dsize += sizeof(sdesc->resolution);
 678
 679			scmi_parse_range_attrs(&s->scalar_attrs,
 680					       &sdesc->scalar_attrs);
 681			dsize += sizeof(sdesc->scalar_attrs);
 682		}
 683	}
 684
 685	if (s->num_axis > 0)
 686		ret = scmi_sensor_axis_description(ph, s, si->version);
 687
 688	st->priv = ((u8 *)sdesc + dsize);
 689
 690	return ret;
 691}
 692
 693static int scmi_sensor_description_get(const struct scmi_protocol_handle *ph,
 694				       struct sensors_info *si)
 695{
 696	void *iter;
 697	struct scmi_iterator_ops ops = {
 698		.prepare_message = iter_sens_descr_prepare_message,
 699		.update_state = iter_sens_descr_update_state,
 700		.process_response = iter_sens_descr_process_response,
 701	};
 702
 703	iter = ph->hops->iter_response_init(ph, &ops, si->num_sensors,
 704					    SENSOR_DESCRIPTION_GET,
 705					    sizeof(__le32), si);
 706	if (IS_ERR(iter))
 707		return PTR_ERR(iter);
 708
 709	return ph->hops->iter_response_run(iter);
 710}
 711
 712static inline int
 713scmi_sensor_request_notify(const struct scmi_protocol_handle *ph, u32 sensor_id,
 714			   u8 message_id, bool enable)
 715{
 716	int ret;
 717	u32 evt_cntl = enable ? SENSOR_NOTIFY_ALL : 0;
 718	struct scmi_xfer *t;
 719	struct scmi_msg_sensor_request_notify *cfg;
 720
 721	ret = ph->xops->xfer_get_init(ph, message_id, sizeof(*cfg), 0, &t);
 722	if (ret)
 723		return ret;
 724
 725	cfg = t->tx.buf;
 726	cfg->id = cpu_to_le32(sensor_id);
 727	cfg->event_control = cpu_to_le32(evt_cntl);
 728
 729	ret = ph->xops->do_xfer(ph, t);
 730
 731	ph->xops->xfer_put(ph, t);
 732	return ret;
 733}
 734
 735static int scmi_sensor_trip_point_notify(const struct scmi_protocol_handle *ph,
 736					 u32 sensor_id, bool enable)
 737{
 738	return scmi_sensor_request_notify(ph, sensor_id,
 739					  SENSOR_TRIP_POINT_NOTIFY,
 740					  enable);
 741}
 742
 743static int
 744scmi_sensor_continuous_update_notify(const struct scmi_protocol_handle *ph,
 745				     u32 sensor_id, bool enable)
 746{
 747	return scmi_sensor_request_notify(ph, sensor_id,
 748					  SENSOR_CONTINUOUS_UPDATE_NOTIFY,
 749					  enable);
 750}
 751
 752static int
 753scmi_sensor_trip_point_config(const struct scmi_protocol_handle *ph,
 754			      u32 sensor_id, u8 trip_id, u64 trip_value)
 755{
 756	int ret;
 757	u32 evt_cntl = SENSOR_TP_BOTH;
 758	struct scmi_xfer *t;
 759	struct scmi_msg_set_sensor_trip_point *trip;
 760
 761	ret = ph->xops->xfer_get_init(ph, SENSOR_TRIP_POINT_CONFIG,
 762				      sizeof(*trip), 0, &t);
 763	if (ret)
 764		return ret;
 765
 766	trip = t->tx.buf;
 767	trip->id = cpu_to_le32(sensor_id);
 768	trip->event_control = cpu_to_le32(evt_cntl | SENSOR_TP_ID(trip_id));
 769	trip->value_low = cpu_to_le32(trip_value & 0xffffffff);
 770	trip->value_high = cpu_to_le32(trip_value >> 32);
 771
 772	ret = ph->xops->do_xfer(ph, t);
 773
 774	ph->xops->xfer_put(ph, t);
 775	return ret;
 776}
 777
 778static int scmi_sensor_config_get(const struct scmi_protocol_handle *ph,
 779				  u32 sensor_id, u32 *sensor_config)
 780{
 781	int ret;
 782	struct scmi_xfer *t;
 783	struct sensors_info *si = ph->get_priv(ph);
 784
 785	if (sensor_id >= si->num_sensors)
 786		return -EINVAL;
 787
 788	ret = ph->xops->xfer_get_init(ph, SENSOR_CONFIG_GET,
 789				      sizeof(__le32), sizeof(__le32), &t);
 790	if (ret)
 791		return ret;
 792
 793	put_unaligned_le32(sensor_id, t->tx.buf);
 794	ret = ph->xops->do_xfer(ph, t);
 795	if (!ret) {
 796		struct scmi_sensor_info *s = si->sensors + sensor_id;
 797
 798		*sensor_config = get_unaligned_le64(t->rx.buf);
 799		s->sensor_config = *sensor_config;
 800	}
 801
 802	ph->xops->xfer_put(ph, t);
 803	return ret;
 804}
 805
 806static int scmi_sensor_config_set(const struct scmi_protocol_handle *ph,
 807				  u32 sensor_id, u32 sensor_config)
 808{
 809	int ret;
 810	struct scmi_xfer *t;
 811	struct scmi_msg_sensor_config_set *msg;
 812	struct sensors_info *si = ph->get_priv(ph);
 813
 814	if (sensor_id >= si->num_sensors)
 815		return -EINVAL;
 816
 817	ret = ph->xops->xfer_get_init(ph, SENSOR_CONFIG_SET,
 818				      sizeof(*msg), 0, &t);
 819	if (ret)
 820		return ret;
 821
 822	msg = t->tx.buf;
 823	msg->id = cpu_to_le32(sensor_id);
 824	msg->sensor_config = cpu_to_le32(sensor_config);
 825
 826	ret = ph->xops->do_xfer(ph, t);
 827	if (!ret) {
 828		struct scmi_sensor_info *s = si->sensors + sensor_id;
 829
 830		s->sensor_config = sensor_config;
 831	}
 832
 833	ph->xops->xfer_put(ph, t);
 834	return ret;
 835}
 836
 837/**
 838 * scmi_sensor_reading_get  - Read scalar sensor value
 839 * @ph: Protocol handle
 840 * @sensor_id: Sensor ID
 841 * @value: The 64bit value sensor reading
 842 *
 843 * This function returns a single 64 bit reading value representing the sensor
 844 * value; if the platform SCMI Protocol implementation and the sensor support
 845 * multiple axis and timestamped-reads, this just returns the first axis while
 846 * dropping the timestamp value.
 847 * Use instead the @scmi_sensor_reading_get_timestamped to retrieve the array of
 848 * timestamped multi-axis values.
 849 *
 850 * Return: 0 on Success
 851 */
 852static int scmi_sensor_reading_get(const struct scmi_protocol_handle *ph,
 853				   u32 sensor_id, u64 *value)
 854{
 855	int ret;
 856	struct scmi_xfer *t;
 857	struct scmi_msg_sensor_reading_get *sensor;
 858	struct scmi_sensor_info *s;
 859	struct sensors_info *si = ph->get_priv(ph);
 860
 861	if (sensor_id >= si->num_sensors)
 862		return -EINVAL;
 863
 864	ret = ph->xops->xfer_get_init(ph, SENSOR_READING_GET,
 865				      sizeof(*sensor), 0, &t);
 866	if (ret)
 867		return ret;
 868
 869	sensor = t->tx.buf;
 870	sensor->id = cpu_to_le32(sensor_id);
 871	s = si->sensors + sensor_id;
 872	if (s->async) {
 873		sensor->flags = cpu_to_le32(SENSOR_READ_ASYNC);
 874		ret = ph->xops->do_xfer_with_response(ph, t);
 875		if (!ret) {
 876			struct scmi_resp_sensor_reading_complete *resp;
 877
 878			resp = t->rx.buf;
 879			if (le32_to_cpu(resp->id) == sensor_id)
 880				*value =
 881					get_unaligned_le64(&resp->readings_low);
 882			else
 883				ret = -EPROTO;
 884		}
 885	} else {
 886		sensor->flags = cpu_to_le32(0);
 887		ret = ph->xops->do_xfer(ph, t);
 888		if (!ret)
 889			*value = get_unaligned_le64(t->rx.buf);
 890	}
 891
 892	ph->xops->xfer_put(ph, t);
 893	return ret;
 894}
 895
 896static inline void
 897scmi_parse_sensor_readings(struct scmi_sensor_reading *out,
 898			   const struct scmi_sensor_reading_resp *in)
 899{
 900	out->value = get_unaligned_le64((void *)&in->sensor_value_low);
 901	out->timestamp = get_unaligned_le64((void *)&in->timestamp_low);
 902}
 903
 904/**
 905 * scmi_sensor_reading_get_timestamped  - Read multiple-axis timestamped values
 906 * @ph: Protocol handle
 907 * @sensor_id: Sensor ID
 908 * @count: The length of the provided @readings array
 909 * @readings: An array of elements each representing a timestamped per-axis
 910 *	      reading of type @struct scmi_sensor_reading.
 911 *	      Returned readings are ordered as the @axis descriptors array
 912 *	      included in @struct scmi_sensor_info and the max number of
 913 *	      returned elements is min(@count, @num_axis); ideally the provided
 914 *	      array should be of length @count equal to @num_axis.
 915 *
 916 * Return: 0 on Success
 917 */
 918static int
 919scmi_sensor_reading_get_timestamped(const struct scmi_protocol_handle *ph,
 920				    u32 sensor_id, u8 count,
 921				    struct scmi_sensor_reading *readings)
 922{
 923	int ret;
 924	struct scmi_xfer *t;
 925	struct scmi_msg_sensor_reading_get *sensor;
 926	struct scmi_sensor_info *s;
 927	struct sensors_info *si = ph->get_priv(ph);
 928
 929	if (sensor_id >= si->num_sensors)
 930		return -EINVAL;
 931
 932	s = si->sensors + sensor_id;
 933	if (!count || !readings ||
 934	    (!s->num_axis && count > 1) || (s->num_axis && count > s->num_axis))
 935		return -EINVAL;
 936
 937	ret = ph->xops->xfer_get_init(ph, SENSOR_READING_GET,
 938				      sizeof(*sensor), 0, &t);
 939	if (ret)
 940		return ret;
 941
 942	sensor = t->tx.buf;
 943	sensor->id = cpu_to_le32(sensor_id);
 944	if (s->async) {
 945		sensor->flags = cpu_to_le32(SENSOR_READ_ASYNC);
 946		ret = ph->xops->do_xfer_with_response(ph, t);
 947		if (!ret) {
 948			int i;
 949			struct scmi_resp_sensor_reading_complete_v3 *resp;
 950
 951			resp = t->rx.buf;
 952			/* Retrieve only the number of requested axis anyway */
 953			if (le32_to_cpu(resp->id) == sensor_id)
 954				for (i = 0; i < count; i++)
 955					scmi_parse_sensor_readings(&readings[i],
 956								   &resp->readings[i]);
 957			else
 958				ret = -EPROTO;
 959		}
 960	} else {
 961		sensor->flags = cpu_to_le32(0);
 962		ret = ph->xops->do_xfer(ph, t);
 963		if (!ret) {
 964			int i;
 965			struct scmi_sensor_reading_resp *resp_readings;
 966
 967			resp_readings = t->rx.buf;
 968			for (i = 0; i < count; i++)
 969				scmi_parse_sensor_readings(&readings[i],
 970							   &resp_readings[i]);
 971		}
 972	}
 973
 974	ph->xops->xfer_put(ph, t);
 975	return ret;
 976}
 977
 978static const struct scmi_sensor_info *
 979scmi_sensor_info_get(const struct scmi_protocol_handle *ph, u32 sensor_id)
 980{
 981	struct sensors_info *si = ph->get_priv(ph);
 982
 983	if (sensor_id >= si->num_sensors)
 984		return NULL;
 985
 986	return si->sensors + sensor_id;
 987}
 988
 989static int scmi_sensor_count_get(const struct scmi_protocol_handle *ph)
 990{
 991	struct sensors_info *si = ph->get_priv(ph);
 992
 993	return si->num_sensors;
 994}
 995
 996static const struct scmi_sensor_proto_ops sensor_proto_ops = {
 997	.count_get = scmi_sensor_count_get,
 998	.info_get = scmi_sensor_info_get,
 999	.trip_point_config = scmi_sensor_trip_point_config,
1000	.reading_get = scmi_sensor_reading_get,
1001	.reading_get_timestamped = scmi_sensor_reading_get_timestamped,
1002	.config_get = scmi_sensor_config_get,
1003	.config_set = scmi_sensor_config_set,
1004};
1005
1006static bool scmi_sensor_notify_supported(const struct scmi_protocol_handle *ph,
1007					 u8 evt_id, u32 src_id)
1008{
1009	bool supported = false;
1010	const struct scmi_sensor_info *s;
1011	struct sensors_info *sinfo = ph->get_priv(ph);
1012
1013	s = scmi_sensor_info_get(ph, src_id);
1014	if (!s)
1015		return false;
1016
1017	if (evt_id == SCMI_EVENT_SENSOR_TRIP_POINT_EVENT)
1018		supported = sinfo->notify_trip_point_cmd;
1019	else if (evt_id == SCMI_EVENT_SENSOR_UPDATE)
1020		supported = s->update;
1021
1022	return supported;
1023}
1024
1025static int scmi_sensor_set_notify_enabled(const struct scmi_protocol_handle *ph,
1026					  u8 evt_id, u32 src_id, bool enable)
1027{
1028	int ret;
1029
1030	switch (evt_id) {
1031	case SCMI_EVENT_SENSOR_TRIP_POINT_EVENT:
1032		ret = scmi_sensor_trip_point_notify(ph, src_id, enable);
1033		break;
1034	case SCMI_EVENT_SENSOR_UPDATE:
1035		ret = scmi_sensor_continuous_update_notify(ph, src_id, enable);
1036		break;
1037	default:
1038		ret = -EINVAL;
1039		break;
1040	}
1041
1042	if (ret)
1043		pr_debug("FAIL_ENABLED - evt[%X] dom[%d] - ret:%d\n",
1044			 evt_id, src_id, ret);
1045
1046	return ret;
1047}
1048
1049static void *
1050scmi_sensor_fill_custom_report(const struct scmi_protocol_handle *ph,
1051			       u8 evt_id, ktime_t timestamp,
1052			       const void *payld, size_t payld_sz,
1053			       void *report, u32 *src_id)
1054{
1055	void *rep = NULL;
1056
1057	switch (evt_id) {
1058	case SCMI_EVENT_SENSOR_TRIP_POINT_EVENT:
1059	{
1060		const struct scmi_sensor_trip_notify_payld *p = payld;
1061		struct scmi_sensor_trip_point_report *r = report;
1062
1063		if (sizeof(*p) != payld_sz)
1064			break;
1065
1066		r->timestamp = timestamp;
1067		r->agent_id = le32_to_cpu(p->agent_id);
1068		r->sensor_id = le32_to_cpu(p->sensor_id);
1069		r->trip_point_desc = le32_to_cpu(p->trip_point_desc);
1070		*src_id = r->sensor_id;
1071		rep = r;
1072		break;
1073	}
1074	case SCMI_EVENT_SENSOR_UPDATE:
1075	{
1076		int i;
1077		struct scmi_sensor_info *s;
1078		const struct scmi_sensor_update_notify_payld *p = payld;
1079		struct scmi_sensor_update_report *r = report;
1080		struct sensors_info *sinfo = ph->get_priv(ph);
1081
1082		/* payld_sz is variable for this event */
1083		r->sensor_id = le32_to_cpu(p->sensor_id);
1084		if (r->sensor_id >= sinfo->num_sensors)
1085			break;
1086		r->timestamp = timestamp;
1087		r->agent_id = le32_to_cpu(p->agent_id);
1088		s = &sinfo->sensors[r->sensor_id];
1089		/*
1090		 * The generated report r (@struct scmi_sensor_update_report)
1091		 * was pre-allocated to contain up to SCMI_MAX_NUM_SENSOR_AXIS
1092		 * readings: here it is filled with the effective @num_axis
1093		 * readings defined for this sensor or 1 for scalar sensors.
1094		 */
1095		r->readings_count = s->num_axis ?: 1;
1096		for (i = 0; i < r->readings_count; i++)
1097			scmi_parse_sensor_readings(&r->readings[i],
1098						   &p->readings[i]);
1099		*src_id = r->sensor_id;
1100		rep = r;
1101		break;
1102	}
1103	default:
1104		break;
1105	}
1106
1107	return rep;
1108}
1109
1110static int scmi_sensor_get_num_sources(const struct scmi_protocol_handle *ph)
1111{
1112	struct sensors_info *si = ph->get_priv(ph);
1113
1114	return si->num_sensors;
1115}
1116
1117static const struct scmi_event sensor_events[] = {
1118	{
1119		.id = SCMI_EVENT_SENSOR_TRIP_POINT_EVENT,
1120		.max_payld_sz = sizeof(struct scmi_sensor_trip_notify_payld),
1121		.max_report_sz = sizeof(struct scmi_sensor_trip_point_report),
1122	},
1123	{
1124		.id = SCMI_EVENT_SENSOR_UPDATE,
1125		.max_payld_sz =
1126			sizeof(struct scmi_sensor_update_notify_payld) +
1127			 SCMI_MAX_NUM_SENSOR_AXIS *
1128			 sizeof(struct scmi_sensor_reading_resp),
1129		.max_report_sz = sizeof(struct scmi_sensor_update_report) +
1130				  SCMI_MAX_NUM_SENSOR_AXIS *
1131				  sizeof(struct scmi_sensor_reading),
1132	},
1133};
1134
1135static const struct scmi_event_ops sensor_event_ops = {
1136	.is_notify_supported = scmi_sensor_notify_supported,
1137	.get_num_sources = scmi_sensor_get_num_sources,
1138	.set_notify_enabled = scmi_sensor_set_notify_enabled,
1139	.fill_custom_report = scmi_sensor_fill_custom_report,
1140};
1141
1142static const struct scmi_protocol_events sensor_protocol_events = {
1143	.queue_sz = SCMI_PROTO_QUEUE_SZ,
1144	.ops = &sensor_event_ops,
1145	.evts = sensor_events,
1146	.num_events = ARRAY_SIZE(sensor_events),
1147};
1148
1149static int scmi_sensors_protocol_init(const struct scmi_protocol_handle *ph)
1150{
1151	u32 version;
1152	int ret;
1153	struct sensors_info *sinfo;
1154
1155	ret = ph->xops->version_get(ph, &version);
1156	if (ret)
1157		return ret;
1158
1159	dev_dbg(ph->dev, "Sensor Version %d.%d\n",
1160		PROTOCOL_REV_MAJOR(version), PROTOCOL_REV_MINOR(version));
1161
1162	sinfo = devm_kzalloc(ph->dev, sizeof(*sinfo), GFP_KERNEL);
1163	if (!sinfo)
1164		return -ENOMEM;
1165	sinfo->version = version;
1166
1167	ret = scmi_sensor_attributes_get(ph, sinfo);
1168	if (ret)
1169		return ret;
1170	sinfo->sensors = devm_kcalloc(ph->dev, sinfo->num_sensors,
1171				      sizeof(*sinfo->sensors), GFP_KERNEL);
1172	if (!sinfo->sensors)
1173		return -ENOMEM;
1174
1175	ret = scmi_sensor_description_get(ph, sinfo);
1176	if (ret)
1177		return ret;
1178
1179	return ph->set_priv(ph, sinfo, version);
1180}
1181
1182static const struct scmi_protocol scmi_sensors = {
1183	.id = SCMI_PROTOCOL_SENSOR,
1184	.owner = THIS_MODULE,
1185	.instance_init = &scmi_sensors_protocol_init,
1186	.ops = &sensor_proto_ops,
1187	.events = &sensor_protocol_events,
1188	.supported_version = SCMI_PROTOCOL_SUPPORTED_VERSION,
1189};
1190
1191DEFINE_SCMI_PROTOCOL_REGISTER_UNREGISTER(sensors, scmi_sensors)