| /* 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 seq_no; | |
| u8 poll_cmd_data; /* to perform OCC poll command */ | |
| int (*send_cmd)(struct occ *occ, u8 *cmd); | |
| unsigned long next_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; /* final transfer error after retry */ | |
| int last_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 */ |