Loading...
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 130 131 132 133 134 135 136 | /* 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, size_t len, void *resp, size_t resp_len); 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]; bool active; 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; u8 prev_ips_status; u8 prev_mode; }; int occ_active(struct occ *occ, bool active); int occ_setup(struct occ *occ); int occ_setup_sysfs(struct occ *occ); void occ_shutdown(struct occ *occ); void occ_shutdown_sysfs(struct occ *occ); void occ_sysfs_poll_done(struct occ *occ); int occ_update_response(struct occ *occ); #endif /* OCC_COMMON_H */ |