Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/drivers/firmware/arm_scmi/sensors.c
29278 views
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
23
enum 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
37
struct 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
64
struct 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
71
struct scmi_msg_sensor_description {
72
__le32 desc_index;
73
};
74
75
struct 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
112
struct scmi_msg_sensor_axis_description_get {
113
__le32 id;
114
__le32 axis_desc_index;
115
};
116
117
struct 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
132
struct 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
143
struct scmi_msg_sensor_list_update_intervals {
144
__le32 id;
145
__le32 index;
146
};
147
148
struct 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
156
struct scmi_msg_sensor_request_notify {
157
__le32 id;
158
__le32 event_control;
159
#define SENSOR_NOTIFY_ALL BIT(0)
160
};
161
162
struct 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
175
struct scmi_msg_sensor_config_set {
176
__le32 id;
177
__le32 sensor_config;
178
};
179
180
struct scmi_msg_sensor_reading_get {
181
__le32 id;
182
__le32 flags;
183
#define SENSOR_READ_ASYNC BIT(0)
184
};
185
186
struct scmi_resp_sensor_reading_complete {
187
__le32 id;
188
__le32 readings_low;
189
__le32 readings_high;
190
};
191
192
struct scmi_sensor_reading_resp {
193
__le32 sensor_value_low;
194
__le32 sensor_value_high;
195
__le32 timestamp_low;
196
__le32 timestamp_high;
197
};
198
199
struct scmi_resp_sensor_reading_complete_v3 {
200
__le32 id;
201
struct scmi_sensor_reading_resp readings[];
202
};
203
204
struct scmi_sensor_trip_notify_payld {
205
__le32 agent_id;
206
__le32 sensor_id;
207
__le32 trip_point_desc;
208
};
209
210
struct scmi_sensor_update_notify_payld {
211
__le32 agent_id;
212
__le32 sensor_id;
213
struct scmi_sensor_reading_resp readings[];
214
};
215
216
struct 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
227
static 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
266
static 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
273
struct scmi_sens_ipriv {
274
void *priv;
275
struct device *dev;
276
};
277
278
static 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
291
static 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
340
static int
341
iter_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
354
static 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
378
struct scmi_apriv {
379
bool any_axes_support_extended_names;
380
struct scmi_sensor_info *s;
381
};
382
383
static 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
395
static int
396
iter_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
410
static int
411
iter_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
449
static int
450
iter_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
464
static int
465
iter_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
490
static int
491
scmi_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
526
static 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
565
static 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
574
static 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
586
static int
587
iter_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
693
static 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
712
static inline int
713
scmi_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
735
static 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
743
static int
744
scmi_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
752
static int
753
scmi_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
778
static 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
806
static 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
*/
852
static 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
896
static inline void
897
scmi_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
*/
918
static int
919
scmi_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
978
static const struct scmi_sensor_info *
979
scmi_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
989
static 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
996
static 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
1006
static 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
1025
static 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
1049
static void *
1050
scmi_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
1110
static 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
1117
static 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
1135
static 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
1142
static 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
1149
static 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
1182
static 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
1191
DEFINE_SCMI_PROTOCOL_REGISTER_UNREGISTER(sensors, scmi_sensors)
1192
1193