blob: ed2cf42452953006e3619fcd68e1cde970d16a39 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
|
/* SPDX-License-Identifier: GPL-2.0+ */
/* Copyright IBM Corp 2019 */
#ifndef OCC_COMMON_H
#define OCC_COMMON_H
#include <linux/hwmon-sysfs.h>
#include <linux/mutex.h>
#include <linux/sysfs.h>
struct device;
#define OCC_RESP_DATA_BYTES 4089
/*
* Same response format for all OCC versions.
* Allocate the largest possible response.
*/
struct occ_response {
u8 seq_no;
u8 cmd_type;
u8 return_status;
__be16 data_length;
u8 data[OCC_RESP_DATA_BYTES];
__be16 checksum;
} __packed;
struct occ_sensor_data_block_header {
u8 eye_catcher[4];
u8 reserved;
u8 sensor_format;
u8 sensor_length;
u8 num_sensors;
} __packed;
struct occ_sensor_data_block {
struct occ_sensor_data_block_header header;
u32 data;
} __packed;
struct occ_poll_response_header {
u8 status;
u8 ext_status;
u8 occs_present;
u8 config_data;
u8 occ_state;
u8 mode;
u8 ips_status;
u8 error_log_id;
__be32 error_log_start_address;
__be16 error_log_length;
u16 reserved;
u8 occ_code_level[16];
u8 eye_catcher[6];
u8 num_sensor_data_blocks;
u8 sensor_data_block_header_version;
} __packed;
struct occ_poll_response {
struct occ_poll_response_header header;
struct occ_sensor_data_block block;
} __packed;
struct occ_sensor {
u8 num_sensors;
u8 version;
void *data; /* pointer to sensor data start within response */
};
/*
* OCC only provides one sensor data block of each type, but any number of
* sensors within that block.
*/
struct occ_sensors {
struct occ_sensor temp;
struct occ_sensor freq;
struct occ_sensor power;
struct occ_sensor caps;
struct occ_sensor extended;
};
/*
* Use our own attribute struct so we can dynamically allocate space for the
* name.
*/
struct occ_attribute {
char name[32];
struct sensor_device_attribute_2 sensor;
};
struct occ {
struct device *bus_dev;
struct occ_response resp;
struct occ_sensors sensors;
int powr_sample_time_us; /* average power sample time */
u8 poll_cmd_data; /* to perform OCC poll command */
int (*send_cmd)(struct occ *occ, u8 *cmd);
unsigned long last_update;
struct mutex lock; /* lock OCC access */
struct device *hwmon;
struct occ_attribute *attrs;
struct attribute_group group;
const struct attribute_group *groups[2];
int error; /* latest transfer error */
unsigned int error_count; /* number of xfr errors observed */
unsigned long last_safe; /* time OCC entered "safe" state */
/*
* Store the previous state data for comparison in order to notify
* sysfs readers of state changes.
*/
int prev_error;
u8 prev_stat;
u8 prev_ext_stat;
u8 prev_occs_present;
};
int occ_setup(struct occ *occ, const char *name);
int occ_setup_sysfs(struct occ *occ);
void occ_shutdown(struct occ *occ);
void occ_sysfs_poll_done(struct occ *occ);
int occ_update_response(struct occ *occ);
#endif /* OCC_COMMON_H */
|