162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0+ */ 262306a36Sopenharmony_ci/* Copyright IBM Corp 2019 */ 362306a36Sopenharmony_ci 462306a36Sopenharmony_ci#ifndef OCC_COMMON_H 562306a36Sopenharmony_ci#define OCC_COMMON_H 662306a36Sopenharmony_ci 762306a36Sopenharmony_ci#include <linux/hwmon-sysfs.h> 862306a36Sopenharmony_ci#include <linux/mutex.h> 962306a36Sopenharmony_ci#include <linux/sysfs.h> 1062306a36Sopenharmony_ci 1162306a36Sopenharmony_cistruct device; 1262306a36Sopenharmony_ci 1362306a36Sopenharmony_ci#define OCC_RESP_DATA_BYTES 4089 1462306a36Sopenharmony_ci 1562306a36Sopenharmony_ci/* 1662306a36Sopenharmony_ci * Same response format for all OCC versions. 1762306a36Sopenharmony_ci * Allocate the largest possible response. 1862306a36Sopenharmony_ci */ 1962306a36Sopenharmony_cistruct occ_response { 2062306a36Sopenharmony_ci u8 seq_no; 2162306a36Sopenharmony_ci u8 cmd_type; 2262306a36Sopenharmony_ci u8 return_status; 2362306a36Sopenharmony_ci __be16 data_length; 2462306a36Sopenharmony_ci u8 data[OCC_RESP_DATA_BYTES]; 2562306a36Sopenharmony_ci __be16 checksum; 2662306a36Sopenharmony_ci} __packed; 2762306a36Sopenharmony_ci 2862306a36Sopenharmony_cistruct occ_sensor_data_block_header { 2962306a36Sopenharmony_ci u8 eye_catcher[4]; 3062306a36Sopenharmony_ci u8 reserved; 3162306a36Sopenharmony_ci u8 sensor_format; 3262306a36Sopenharmony_ci u8 sensor_length; 3362306a36Sopenharmony_ci u8 num_sensors; 3462306a36Sopenharmony_ci} __packed; 3562306a36Sopenharmony_ci 3662306a36Sopenharmony_cistruct occ_sensor_data_block { 3762306a36Sopenharmony_ci struct occ_sensor_data_block_header header; 3862306a36Sopenharmony_ci u32 data; 3962306a36Sopenharmony_ci} __packed; 4062306a36Sopenharmony_ci 4162306a36Sopenharmony_cistruct occ_poll_response_header { 4262306a36Sopenharmony_ci u8 status; 4362306a36Sopenharmony_ci u8 ext_status; 4462306a36Sopenharmony_ci u8 occs_present; 4562306a36Sopenharmony_ci u8 config_data; 4662306a36Sopenharmony_ci u8 occ_state; 4762306a36Sopenharmony_ci u8 mode; 4862306a36Sopenharmony_ci u8 ips_status; 4962306a36Sopenharmony_ci u8 error_log_id; 5062306a36Sopenharmony_ci __be32 error_log_start_address; 5162306a36Sopenharmony_ci __be16 error_log_length; 5262306a36Sopenharmony_ci u16 reserved; 5362306a36Sopenharmony_ci u8 occ_code_level[16]; 5462306a36Sopenharmony_ci u8 eye_catcher[6]; 5562306a36Sopenharmony_ci u8 num_sensor_data_blocks; 5662306a36Sopenharmony_ci u8 sensor_data_block_header_version; 5762306a36Sopenharmony_ci} __packed; 5862306a36Sopenharmony_ci 5962306a36Sopenharmony_cistruct occ_poll_response { 6062306a36Sopenharmony_ci struct occ_poll_response_header header; 6162306a36Sopenharmony_ci struct occ_sensor_data_block block; 6262306a36Sopenharmony_ci} __packed; 6362306a36Sopenharmony_ci 6462306a36Sopenharmony_cistruct occ_sensor { 6562306a36Sopenharmony_ci u8 num_sensors; 6662306a36Sopenharmony_ci u8 version; 6762306a36Sopenharmony_ci void *data; /* pointer to sensor data start within response */ 6862306a36Sopenharmony_ci}; 6962306a36Sopenharmony_ci 7062306a36Sopenharmony_ci/* 7162306a36Sopenharmony_ci * OCC only provides one sensor data block of each type, but any number of 7262306a36Sopenharmony_ci * sensors within that block. 7362306a36Sopenharmony_ci */ 7462306a36Sopenharmony_cistruct occ_sensors { 7562306a36Sopenharmony_ci struct occ_sensor temp; 7662306a36Sopenharmony_ci struct occ_sensor freq; 7762306a36Sopenharmony_ci struct occ_sensor power; 7862306a36Sopenharmony_ci struct occ_sensor caps; 7962306a36Sopenharmony_ci struct occ_sensor extended; 8062306a36Sopenharmony_ci}; 8162306a36Sopenharmony_ci 8262306a36Sopenharmony_ci/* 8362306a36Sopenharmony_ci * Use our own attribute struct so we can dynamically allocate space for the 8462306a36Sopenharmony_ci * name. 8562306a36Sopenharmony_ci */ 8662306a36Sopenharmony_cistruct occ_attribute { 8762306a36Sopenharmony_ci char name[32]; 8862306a36Sopenharmony_ci struct sensor_device_attribute_2 sensor; 8962306a36Sopenharmony_ci}; 9062306a36Sopenharmony_ci 9162306a36Sopenharmony_cistruct occ { 9262306a36Sopenharmony_ci struct device *bus_dev; 9362306a36Sopenharmony_ci 9462306a36Sopenharmony_ci struct occ_response resp; 9562306a36Sopenharmony_ci struct occ_sensors sensors; 9662306a36Sopenharmony_ci 9762306a36Sopenharmony_ci int powr_sample_time_us; /* average power sample time */ 9862306a36Sopenharmony_ci u8 poll_cmd_data; /* to perform OCC poll command */ 9962306a36Sopenharmony_ci int (*send_cmd)(struct occ *occ, u8 *cmd, size_t len, void *resp, 10062306a36Sopenharmony_ci size_t resp_len); 10162306a36Sopenharmony_ci 10262306a36Sopenharmony_ci unsigned long next_update; 10362306a36Sopenharmony_ci struct mutex lock; /* lock OCC access */ 10462306a36Sopenharmony_ci 10562306a36Sopenharmony_ci struct device *hwmon; 10662306a36Sopenharmony_ci struct occ_attribute *attrs; 10762306a36Sopenharmony_ci struct attribute_group group; 10862306a36Sopenharmony_ci const struct attribute_group *groups[2]; 10962306a36Sopenharmony_ci 11062306a36Sopenharmony_ci bool active; 11162306a36Sopenharmony_ci int error; /* final transfer error after retry */ 11262306a36Sopenharmony_ci int last_error; /* latest transfer error */ 11362306a36Sopenharmony_ci unsigned int error_count; /* number of xfr errors observed */ 11462306a36Sopenharmony_ci unsigned long last_safe; /* time OCC entered "safe" state */ 11562306a36Sopenharmony_ci 11662306a36Sopenharmony_ci /* 11762306a36Sopenharmony_ci * Store the previous state data for comparison in order to notify 11862306a36Sopenharmony_ci * sysfs readers of state changes. 11962306a36Sopenharmony_ci */ 12062306a36Sopenharmony_ci int prev_error; 12162306a36Sopenharmony_ci u8 prev_stat; 12262306a36Sopenharmony_ci u8 prev_ext_stat; 12362306a36Sopenharmony_ci u8 prev_occs_present; 12462306a36Sopenharmony_ci u8 prev_ips_status; 12562306a36Sopenharmony_ci u8 prev_mode; 12662306a36Sopenharmony_ci}; 12762306a36Sopenharmony_ci 12862306a36Sopenharmony_ciint occ_active(struct occ *occ, bool active); 12962306a36Sopenharmony_ciint occ_setup(struct occ *occ); 13062306a36Sopenharmony_ciint occ_setup_sysfs(struct occ *occ); 13162306a36Sopenharmony_civoid occ_shutdown(struct occ *occ); 13262306a36Sopenharmony_civoid occ_shutdown_sysfs(struct occ *occ); 13362306a36Sopenharmony_civoid occ_sysfs_poll_done(struct occ *occ); 13462306a36Sopenharmony_ciint occ_update_response(struct occ *occ); 13562306a36Sopenharmony_ci 13662306a36Sopenharmony_ci#endif /* OCC_COMMON_H */ 137