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