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