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