18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0+ */ 28c2ecf20Sopenharmony_ci/* Copyright IBM Corp 2019 */ 38c2ecf20Sopenharmony_ci 48c2ecf20Sopenharmony_ci#ifndef OCC_COMMON_H 58c2ecf20Sopenharmony_ci#define OCC_COMMON_H 68c2ecf20Sopenharmony_ci 78c2ecf20Sopenharmony_ci#include <linux/hwmon-sysfs.h> 88c2ecf20Sopenharmony_ci#include <linux/mutex.h> 98c2ecf20Sopenharmony_ci#include <linux/sysfs.h> 108c2ecf20Sopenharmony_ci 118c2ecf20Sopenharmony_cistruct device; 128c2ecf20Sopenharmony_ci 138c2ecf20Sopenharmony_ci#define OCC_RESP_DATA_BYTES 4089 148c2ecf20Sopenharmony_ci 158c2ecf20Sopenharmony_ci/* 168c2ecf20Sopenharmony_ci * Same response format for all OCC versions. 178c2ecf20Sopenharmony_ci * Allocate the largest possible response. 188c2ecf20Sopenharmony_ci */ 198c2ecf20Sopenharmony_cistruct occ_response { 208c2ecf20Sopenharmony_ci u8 seq_no; 218c2ecf20Sopenharmony_ci u8 cmd_type; 228c2ecf20Sopenharmony_ci u8 return_status; 238c2ecf20Sopenharmony_ci __be16 data_length; 248c2ecf20Sopenharmony_ci u8 data[OCC_RESP_DATA_BYTES]; 258c2ecf20Sopenharmony_ci __be16 checksum; 268c2ecf20Sopenharmony_ci} __packed; 278c2ecf20Sopenharmony_ci 288c2ecf20Sopenharmony_cistruct occ_sensor_data_block_header { 298c2ecf20Sopenharmony_ci u8 eye_catcher[4]; 308c2ecf20Sopenharmony_ci u8 reserved; 318c2ecf20Sopenharmony_ci u8 sensor_format; 328c2ecf20Sopenharmony_ci u8 sensor_length; 338c2ecf20Sopenharmony_ci u8 num_sensors; 348c2ecf20Sopenharmony_ci} __packed; 358c2ecf20Sopenharmony_ci 368c2ecf20Sopenharmony_cistruct occ_sensor_data_block { 378c2ecf20Sopenharmony_ci struct occ_sensor_data_block_header header; 388c2ecf20Sopenharmony_ci u32 data; 398c2ecf20Sopenharmony_ci} __packed; 408c2ecf20Sopenharmony_ci 418c2ecf20Sopenharmony_cistruct occ_poll_response_header { 428c2ecf20Sopenharmony_ci u8 status; 438c2ecf20Sopenharmony_ci u8 ext_status; 448c2ecf20Sopenharmony_ci u8 occs_present; 458c2ecf20Sopenharmony_ci u8 config_data; 468c2ecf20Sopenharmony_ci u8 occ_state; 478c2ecf20Sopenharmony_ci u8 mode; 488c2ecf20Sopenharmony_ci u8 ips_status; 498c2ecf20Sopenharmony_ci u8 error_log_id; 508c2ecf20Sopenharmony_ci __be32 error_log_start_address; 518c2ecf20Sopenharmony_ci __be16 error_log_length; 528c2ecf20Sopenharmony_ci u16 reserved; 538c2ecf20Sopenharmony_ci u8 occ_code_level[16]; 548c2ecf20Sopenharmony_ci u8 eye_catcher[6]; 558c2ecf20Sopenharmony_ci u8 num_sensor_data_blocks; 568c2ecf20Sopenharmony_ci u8 sensor_data_block_header_version; 578c2ecf20Sopenharmony_ci} __packed; 588c2ecf20Sopenharmony_ci 598c2ecf20Sopenharmony_cistruct occ_poll_response { 608c2ecf20Sopenharmony_ci struct occ_poll_response_header header; 618c2ecf20Sopenharmony_ci struct occ_sensor_data_block block; 628c2ecf20Sopenharmony_ci} __packed; 638c2ecf20Sopenharmony_ci 648c2ecf20Sopenharmony_cistruct occ_sensor { 658c2ecf20Sopenharmony_ci u8 num_sensors; 668c2ecf20Sopenharmony_ci u8 version; 678c2ecf20Sopenharmony_ci void *data; /* pointer to sensor data start within response */ 688c2ecf20Sopenharmony_ci}; 698c2ecf20Sopenharmony_ci 708c2ecf20Sopenharmony_ci/* 718c2ecf20Sopenharmony_ci * OCC only provides one sensor data block of each type, but any number of 728c2ecf20Sopenharmony_ci * sensors within that block. 738c2ecf20Sopenharmony_ci */ 748c2ecf20Sopenharmony_cistruct occ_sensors { 758c2ecf20Sopenharmony_ci struct occ_sensor temp; 768c2ecf20Sopenharmony_ci struct occ_sensor freq; 778c2ecf20Sopenharmony_ci struct occ_sensor power; 788c2ecf20Sopenharmony_ci struct occ_sensor caps; 798c2ecf20Sopenharmony_ci struct occ_sensor extended; 808c2ecf20Sopenharmony_ci}; 818c2ecf20Sopenharmony_ci 828c2ecf20Sopenharmony_ci/* 838c2ecf20Sopenharmony_ci * Use our own attribute struct so we can dynamically allocate space for the 848c2ecf20Sopenharmony_ci * name. 858c2ecf20Sopenharmony_ci */ 868c2ecf20Sopenharmony_cistruct occ_attribute { 878c2ecf20Sopenharmony_ci char name[32]; 888c2ecf20Sopenharmony_ci struct sensor_device_attribute_2 sensor; 898c2ecf20Sopenharmony_ci}; 908c2ecf20Sopenharmony_ci 918c2ecf20Sopenharmony_cistruct occ { 928c2ecf20Sopenharmony_ci struct device *bus_dev; 938c2ecf20Sopenharmony_ci 948c2ecf20Sopenharmony_ci struct occ_response resp; 958c2ecf20Sopenharmony_ci struct occ_sensors sensors; 968c2ecf20Sopenharmony_ci 978c2ecf20Sopenharmony_ci int powr_sample_time_us; /* average power sample time */ 988c2ecf20Sopenharmony_ci u8 seq_no; 998c2ecf20Sopenharmony_ci u8 poll_cmd_data; /* to perform OCC poll command */ 1008c2ecf20Sopenharmony_ci int (*send_cmd)(struct occ *occ, u8 *cmd); 1018c2ecf20Sopenharmony_ci 1028c2ecf20Sopenharmony_ci unsigned long next_update; 1038c2ecf20Sopenharmony_ci struct mutex lock; /* lock OCC access */ 1048c2ecf20Sopenharmony_ci 1058c2ecf20Sopenharmony_ci struct device *hwmon; 1068c2ecf20Sopenharmony_ci struct occ_attribute *attrs; 1078c2ecf20Sopenharmony_ci struct attribute_group group; 1088c2ecf20Sopenharmony_ci const struct attribute_group *groups[2]; 1098c2ecf20Sopenharmony_ci 1108c2ecf20Sopenharmony_ci int error; /* final transfer error after retry */ 1118c2ecf20Sopenharmony_ci int last_error; /* latest transfer error */ 1128c2ecf20Sopenharmony_ci unsigned int error_count; /* number of xfr errors observed */ 1138c2ecf20Sopenharmony_ci unsigned long last_safe; /* time OCC entered "safe" state */ 1148c2ecf20Sopenharmony_ci 1158c2ecf20Sopenharmony_ci /* 1168c2ecf20Sopenharmony_ci * Store the previous state data for comparison in order to notify 1178c2ecf20Sopenharmony_ci * sysfs readers of state changes. 1188c2ecf20Sopenharmony_ci */ 1198c2ecf20Sopenharmony_ci int prev_error; 1208c2ecf20Sopenharmony_ci u8 prev_stat; 1218c2ecf20Sopenharmony_ci u8 prev_ext_stat; 1228c2ecf20Sopenharmony_ci u8 prev_occs_present; 1238c2ecf20Sopenharmony_ci}; 1248c2ecf20Sopenharmony_ci 1258c2ecf20Sopenharmony_ciint occ_setup(struct occ *occ, const char *name); 1268c2ecf20Sopenharmony_ciint occ_setup_sysfs(struct occ *occ); 1278c2ecf20Sopenharmony_civoid occ_shutdown(struct occ *occ); 1288c2ecf20Sopenharmony_civoid occ_sysfs_poll_done(struct occ *occ); 1298c2ecf20Sopenharmony_ciint occ_update_response(struct occ *occ); 1308c2ecf20Sopenharmony_ci 1318c2ecf20Sopenharmony_ci#endif /* OCC_COMMON_H */ 132