437 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			437 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/* SPDX-License-Identifier: GPL-2.0 */
 | 
						|
/*
 | 
						|
 * AMD Platform Management Framework Driver
 | 
						|
 *
 | 
						|
 * Copyright (c) 2022, Advanced Micro Devices, Inc.
 | 
						|
 * All Rights Reserved.
 | 
						|
 *
 | 
						|
 * Author: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
 | 
						|
 */
 | 
						|
 | 
						|
#ifndef PMF_H
 | 
						|
#define PMF_H
 | 
						|
 | 
						|
#include <linux/acpi.h>
 | 
						|
#include <linux/platform_profile.h>
 | 
						|
 | 
						|
/* APMF Functions */
 | 
						|
#define APMF_FUNC_VERIFY_INTERFACE			0
 | 
						|
#define APMF_FUNC_GET_SYS_PARAMS			1
 | 
						|
#define APMF_FUNC_SBIOS_REQUESTS			2
 | 
						|
#define APMF_FUNC_SBIOS_HEARTBEAT			4
 | 
						|
#define APMF_FUNC_AUTO_MODE					5
 | 
						|
#define APMF_FUNC_SET_FAN_IDX				7
 | 
						|
#define APMF_FUNC_OS_POWER_SLIDER_UPDATE		8
 | 
						|
#define APMF_FUNC_STATIC_SLIDER_GRANULAR       9
 | 
						|
#define APMF_FUNC_DYN_SLIDER_AC				11
 | 
						|
#define APMF_FUNC_DYN_SLIDER_DC				12
 | 
						|
 | 
						|
/* Message Definitions */
 | 
						|
#define SET_SPL				0x03 /* SPL: Sustained Power Limit */
 | 
						|
#define SET_SPPT			0x05 /* SPPT: Slow Package Power Tracking */
 | 
						|
#define SET_FPPT			0x07 /* FPPT: Fast Package Power Tracking */
 | 
						|
#define GET_SPL				0x0B
 | 
						|
#define GET_SPPT			0x0D
 | 
						|
#define GET_FPPT			0x0F
 | 
						|
#define SET_DRAM_ADDR_HIGH	0x14
 | 
						|
#define SET_DRAM_ADDR_LOW	0x15
 | 
						|
#define SET_TRANSFER_TABLE	0x16
 | 
						|
#define SET_STT_MIN_LIMIT	0x18 /* STT: Skin Temperature Tracking */
 | 
						|
#define SET_STT_LIMIT_APU	0x19
 | 
						|
#define SET_STT_LIMIT_HS2	0x1A
 | 
						|
#define SET_SPPT_APU_ONLY	0x1D
 | 
						|
#define GET_SPPT_APU_ONLY	0x1E
 | 
						|
#define GET_STT_MIN_LIMIT	0x1F
 | 
						|
#define GET_STT_LIMIT_APU	0x20
 | 
						|
#define GET_STT_LIMIT_HS2	0x21
 | 
						|
 | 
						|
/* OS slider update notification */
 | 
						|
#define DC_BEST_PERF		0
 | 
						|
#define DC_BETTER_PERF		1
 | 
						|
#define DC_BATTERY_SAVER	3
 | 
						|
#define AC_BEST_PERF		4
 | 
						|
#define AC_BETTER_PERF		5
 | 
						|
#define AC_BETTER_BATTERY	6
 | 
						|
 | 
						|
/* Fan Index for Auto Mode */
 | 
						|
#define FAN_INDEX_AUTO		0xFFFFFFFF
 | 
						|
 | 
						|
#define ARG_NONE 0
 | 
						|
#define AVG_SAMPLE_SIZE 3
 | 
						|
 | 
						|
/* AMD PMF BIOS interfaces */
 | 
						|
struct apmf_verify_interface {
 | 
						|
	u16 size;
 | 
						|
	u16 version;
 | 
						|
	u32 notification_mask;
 | 
						|
	u32 supported_functions;
 | 
						|
} __packed;
 | 
						|
 | 
						|
struct apmf_system_params {
 | 
						|
	u16 size;
 | 
						|
	u32 valid_mask;
 | 
						|
	u32 flags;
 | 
						|
	u8 command_code;
 | 
						|
	u32 heartbeat_int;
 | 
						|
} __packed;
 | 
						|
 | 
						|
struct apmf_sbios_req {
 | 
						|
	u16 size;
 | 
						|
	u32 pending_req;
 | 
						|
	u8 rsd;
 | 
						|
	u8 cql_event;
 | 
						|
	u8 amt_event;
 | 
						|
	u32 fppt;
 | 
						|
	u32 sppt;
 | 
						|
	u32 fppt_apu_only;
 | 
						|
	u32 spl;
 | 
						|
	u32 stt_min_limit;
 | 
						|
	u8 skin_temp_apu;
 | 
						|
	u8 skin_temp_hs2;
 | 
						|
} __packed;
 | 
						|
 | 
						|
struct apmf_fan_idx {
 | 
						|
	u16 size;
 | 
						|
	u8 fan_ctl_mode;
 | 
						|
	u32 fan_ctl_idx;
 | 
						|
} __packed;
 | 
						|
 | 
						|
struct smu_pmf_metrics {
 | 
						|
	u16 gfxclk_freq; /* in MHz */
 | 
						|
	u16 socclk_freq; /* in MHz */
 | 
						|
	u16 vclk_freq; /* in MHz */
 | 
						|
	u16 dclk_freq; /* in MHz */
 | 
						|
	u16 memclk_freq; /* in MHz */
 | 
						|
	u16 spare;
 | 
						|
	u16 gfx_activity; /* in Centi */
 | 
						|
	u16 uvd_activity; /* in Centi */
 | 
						|
	u16 voltage[2]; /* in mV */
 | 
						|
	u16 currents[2]; /* in mA */
 | 
						|
	u16 power[2];/* in mW */
 | 
						|
	u16 core_freq[8]; /* in MHz */
 | 
						|
	u16 core_power[8]; /* in mW */
 | 
						|
	u16 core_temp[8]; /* in centi-Celsius */
 | 
						|
	u16 l3_freq; /* in MHz */
 | 
						|
	u16 l3_temp; /* in centi-Celsius */
 | 
						|
	u16 gfx_temp; /* in centi-Celsius */
 | 
						|
	u16 soc_temp; /* in centi-Celsius */
 | 
						|
	u16 throttler_status;
 | 
						|
	u16 current_socketpower; /* in mW */
 | 
						|
	u16 stapm_orig_limit; /* in W */
 | 
						|
	u16 stapm_cur_limit; /* in W */
 | 
						|
	u32 apu_power; /* in mW */
 | 
						|
	u32 dgpu_power; /* in mW */
 | 
						|
	u16 vdd_tdc_val; /* in mA */
 | 
						|
	u16 soc_tdc_val; /* in mA */
 | 
						|
	u16 vdd_edc_val; /* in mA */
 | 
						|
	u16 soc_edcv_al; /* in mA */
 | 
						|
	u16 infra_cpu_maxfreq; /* in MHz */
 | 
						|
	u16 infra_gfx_maxfreq; /* in MHz */
 | 
						|
	u16 skin_temp; /* in centi-Celsius */
 | 
						|
	u16 device_state;
 | 
						|
} __packed;
 | 
						|
 | 
						|
enum amd_stt_skin_temp {
 | 
						|
	STT_TEMP_APU,
 | 
						|
	STT_TEMP_HS2,
 | 
						|
	STT_TEMP_COUNT,
 | 
						|
};
 | 
						|
 | 
						|
enum amd_slider_op {
 | 
						|
	SLIDER_OP_GET,
 | 
						|
	SLIDER_OP_SET,
 | 
						|
};
 | 
						|
 | 
						|
enum power_source {
 | 
						|
	POWER_SOURCE_AC,
 | 
						|
	POWER_SOURCE_DC,
 | 
						|
	POWER_SOURCE_MAX,
 | 
						|
};
 | 
						|
 | 
						|
enum power_modes {
 | 
						|
	POWER_MODE_PERFORMANCE,
 | 
						|
	POWER_MODE_BALANCED_POWER,
 | 
						|
	POWER_MODE_POWER_SAVER,
 | 
						|
	POWER_MODE_MAX,
 | 
						|
};
 | 
						|
 | 
						|
struct amd_pmf_dev {
 | 
						|
	void __iomem *regbase;
 | 
						|
	void __iomem *smu_virt_addr;
 | 
						|
	void *buf;
 | 
						|
	u32 base_addr;
 | 
						|
	u32 cpu_id;
 | 
						|
	struct device *dev;
 | 
						|
	struct mutex lock; /* protects the PMF interface */
 | 
						|
	u32 supported_func;
 | 
						|
	enum platform_profile_option current_profile;
 | 
						|
	struct platform_profile_handler pprof;
 | 
						|
	struct dentry *dbgfs_dir;
 | 
						|
	int hb_interval; /* SBIOS heartbeat interval */
 | 
						|
	struct delayed_work heart_beat;
 | 
						|
	struct smu_pmf_metrics m_table;
 | 
						|
	struct delayed_work work_buffer;
 | 
						|
	ktime_t start_time;
 | 
						|
	int socket_power_history[AVG_SAMPLE_SIZE];
 | 
						|
	int socket_power_history_idx;
 | 
						|
	bool amt_enabled;
 | 
						|
	struct mutex update_mutex; /* protects race between ACPI handler and metrics thread */
 | 
						|
	bool cnqf_enabled;
 | 
						|
	bool cnqf_supported;
 | 
						|
	struct notifier_block pwr_src_notifier;
 | 
						|
};
 | 
						|
 | 
						|
struct apmf_sps_prop_granular {
 | 
						|
	u32 fppt;
 | 
						|
	u32 sppt;
 | 
						|
	u32 sppt_apu_only;
 | 
						|
	u32 spl;
 | 
						|
	u32 stt_min;
 | 
						|
	u8 stt_skin_temp[STT_TEMP_COUNT];
 | 
						|
	u32 fan_id;
 | 
						|
} __packed;
 | 
						|
 | 
						|
/* Static Slider */
 | 
						|
struct apmf_static_slider_granular_output {
 | 
						|
	u16 size;
 | 
						|
	struct apmf_sps_prop_granular prop[POWER_SOURCE_MAX * POWER_MODE_MAX];
 | 
						|
} __packed;
 | 
						|
 | 
						|
struct amd_pmf_static_slider_granular {
 | 
						|
	u16 size;
 | 
						|
	struct apmf_sps_prop_granular prop[POWER_SOURCE_MAX][POWER_MODE_MAX];
 | 
						|
};
 | 
						|
 | 
						|
struct os_power_slider {
 | 
						|
	u16 size;
 | 
						|
	u8 slider_event;
 | 
						|
} __packed;
 | 
						|
 | 
						|
struct fan_table_control {
 | 
						|
	bool manual;
 | 
						|
	unsigned long fan_id;
 | 
						|
};
 | 
						|
 | 
						|
struct power_table_control {
 | 
						|
	u32 spl;
 | 
						|
	u32 sppt;
 | 
						|
	u32 fppt;
 | 
						|
	u32 sppt_apu_only;
 | 
						|
	u32 stt_min;
 | 
						|
	u32 stt_skin_temp[STT_TEMP_COUNT];
 | 
						|
	u32 reserved[16];
 | 
						|
};
 | 
						|
 | 
						|
/* Auto Mode Layer */
 | 
						|
enum auto_mode_transition_priority {
 | 
						|
	AUTO_TRANSITION_TO_PERFORMANCE, /* Any other mode to Performance Mode */
 | 
						|
	AUTO_TRANSITION_FROM_QUIET_TO_BALANCE, /* Quiet Mode to Balance Mode */
 | 
						|
	AUTO_TRANSITION_TO_QUIET, /* Any other mode to Quiet Mode */
 | 
						|
	AUTO_TRANSITION_FROM_PERFORMANCE_TO_BALANCE, /* Performance Mode to Balance Mode */
 | 
						|
	AUTO_TRANSITION_MAX,
 | 
						|
};
 | 
						|
 | 
						|
enum auto_mode_mode {
 | 
						|
	AUTO_QUIET,
 | 
						|
	AUTO_BALANCE,
 | 
						|
	AUTO_PERFORMANCE_ON_LAP,
 | 
						|
	AUTO_PERFORMANCE,
 | 
						|
	AUTO_MODE_MAX,
 | 
						|
};
 | 
						|
 | 
						|
struct auto_mode_trans_params {
 | 
						|
	u32 time_constant; /* minimum time required to switch to next mode */
 | 
						|
	u32 power_delta; /* delta power to shift mode */
 | 
						|
	u32 power_threshold;
 | 
						|
	u32 timer; /* elapsed time. if timer > TimeThreshold, it will move to next mode */
 | 
						|
	u32 applied;
 | 
						|
	enum auto_mode_mode target_mode;
 | 
						|
	u32 shifting_up;
 | 
						|
};
 | 
						|
 | 
						|
struct auto_mode_mode_settings {
 | 
						|
	struct power_table_control power_control;
 | 
						|
	struct fan_table_control fan_control;
 | 
						|
	u32 power_floor;
 | 
						|
};
 | 
						|
 | 
						|
struct auto_mode_mode_config {
 | 
						|
	struct auto_mode_trans_params transition[AUTO_TRANSITION_MAX];
 | 
						|
	struct auto_mode_mode_settings mode_set[AUTO_MODE_MAX];
 | 
						|
	enum auto_mode_mode current_mode;
 | 
						|
};
 | 
						|
 | 
						|
struct apmf_auto_mode {
 | 
						|
	u16 size;
 | 
						|
	/* time constant */
 | 
						|
	u32 balanced_to_perf;
 | 
						|
	u32 perf_to_balanced;
 | 
						|
	u32 quiet_to_balanced;
 | 
						|
	u32 balanced_to_quiet;
 | 
						|
	/* power floor */
 | 
						|
	u32 pfloor_perf;
 | 
						|
	u32 pfloor_balanced;
 | 
						|
	u32 pfloor_quiet;
 | 
						|
	/* Power delta for mode change */
 | 
						|
	u32 pd_balanced_to_perf;
 | 
						|
	u32 pd_perf_to_balanced;
 | 
						|
	u32 pd_quiet_to_balanced;
 | 
						|
	u32 pd_balanced_to_quiet;
 | 
						|
	/* skin temperature limits */
 | 
						|
	u8 stt_apu_perf_on_lap; /* CQL ON */
 | 
						|
	u8 stt_hs2_perf_on_lap; /* CQL ON */
 | 
						|
	u8 stt_apu_perf;
 | 
						|
	u8 stt_hs2_perf;
 | 
						|
	u8 stt_apu_balanced;
 | 
						|
	u8 stt_hs2_balanced;
 | 
						|
	u8 stt_apu_quiet;
 | 
						|
	u8 stt_hs2_quiet;
 | 
						|
	u32 stt_min_limit_perf_on_lap; /* CQL ON */
 | 
						|
	u32 stt_min_limit_perf;
 | 
						|
	u32 stt_min_limit_balanced;
 | 
						|
	u32 stt_min_limit_quiet;
 | 
						|
	/* SPL based */
 | 
						|
	u32 fppt_perf_on_lap; /* CQL ON */
 | 
						|
	u32 sppt_perf_on_lap; /* CQL ON */
 | 
						|
	u32 spl_perf_on_lap; /* CQL ON */
 | 
						|
	u32 sppt_apu_only_perf_on_lap; /* CQL ON */
 | 
						|
	u32 fppt_perf;
 | 
						|
	u32 sppt_perf;
 | 
						|
	u32 spl_perf;
 | 
						|
	u32 sppt_apu_only_perf;
 | 
						|
	u32 fppt_balanced;
 | 
						|
	u32 sppt_balanced;
 | 
						|
	u32 spl_balanced;
 | 
						|
	u32 sppt_apu_only_balanced;
 | 
						|
	u32 fppt_quiet;
 | 
						|
	u32 sppt_quiet;
 | 
						|
	u32 spl_quiet;
 | 
						|
	u32 sppt_apu_only_quiet;
 | 
						|
	/* Fan ID */
 | 
						|
	u32 fan_id_perf;
 | 
						|
	u32 fan_id_balanced;
 | 
						|
	u32 fan_id_quiet;
 | 
						|
} __packed;
 | 
						|
 | 
						|
/* CnQF Layer */
 | 
						|
enum cnqf_trans_priority {
 | 
						|
	CNQF_TRANSITION_TO_TURBO, /* Any other mode to Turbo Mode */
 | 
						|
	CNQF_TRANSITION_FROM_BALANCE_TO_PERFORMANCE, /* quiet/balance to Performance Mode */
 | 
						|
	CNQF_TRANSITION_FROM_QUIET_TO_BALANCE, /* Quiet Mode to Balance Mode */
 | 
						|
	CNQF_TRANSITION_TO_QUIET, /* Any other mode to Quiet Mode */
 | 
						|
	CNQF_TRANSITION_FROM_PERFORMANCE_TO_BALANCE, /* Performance/Turbo to Balance Mode */
 | 
						|
	CNQF_TRANSITION_FROM_TURBO_TO_PERFORMANCE, /* Turbo mode to Performance Mode */
 | 
						|
	CNQF_TRANSITION_MAX,
 | 
						|
};
 | 
						|
 | 
						|
enum cnqf_mode {
 | 
						|
	CNQF_MODE_QUIET,
 | 
						|
	CNQF_MODE_BALANCE,
 | 
						|
	CNQF_MODE_PERFORMANCE,
 | 
						|
	CNQF_MODE_TURBO,
 | 
						|
	CNQF_MODE_MAX,
 | 
						|
};
 | 
						|
 | 
						|
enum apmf_cnqf_pos {
 | 
						|
	APMF_CNQF_TURBO,
 | 
						|
	APMF_CNQF_PERFORMANCE,
 | 
						|
	APMF_CNQF_BALANCE,
 | 
						|
	APMF_CNQF_QUIET,
 | 
						|
	APMF_CNQF_MAX,
 | 
						|
};
 | 
						|
 | 
						|
struct cnqf_mode_settings {
 | 
						|
	struct power_table_control power_control;
 | 
						|
	struct fan_table_control fan_control;
 | 
						|
	u32 power_floor;
 | 
						|
};
 | 
						|
 | 
						|
struct cnqf_tran_params {
 | 
						|
	u32 time_constant; /* minimum time required to switch to next mode */
 | 
						|
	u32 power_threshold;
 | 
						|
	u32 timer; /* elapsed time. if timer > timethreshold, it will move to next mode */
 | 
						|
	u32 total_power;
 | 
						|
	u32 count;
 | 
						|
	bool priority;
 | 
						|
	bool shifting_up;
 | 
						|
	enum cnqf_mode target_mode;
 | 
						|
};
 | 
						|
 | 
						|
struct cnqf_config {
 | 
						|
	struct cnqf_tran_params trans_param[POWER_SOURCE_MAX][CNQF_TRANSITION_MAX];
 | 
						|
	struct cnqf_mode_settings mode_set[POWER_SOURCE_MAX][CNQF_MODE_MAX];
 | 
						|
	struct power_table_control defaults;
 | 
						|
	enum cnqf_mode current_mode;
 | 
						|
	u32 power_src;
 | 
						|
	u32 avg_power;
 | 
						|
};
 | 
						|
 | 
						|
struct apmf_cnqf_power_set {
 | 
						|
	u32 pfloor;
 | 
						|
	u32 fppt;
 | 
						|
	u32 sppt;
 | 
						|
	u32 sppt_apu_only;
 | 
						|
	u32 spl;
 | 
						|
	u32 stt_min_limit;
 | 
						|
	u8 stt_skintemp[STT_TEMP_COUNT];
 | 
						|
	u32 fan_id;
 | 
						|
} __packed;
 | 
						|
 | 
						|
struct apmf_dyn_slider_output {
 | 
						|
	u16 size;
 | 
						|
	u16 flags;
 | 
						|
	u32 t_perf_to_turbo;
 | 
						|
	u32 t_balanced_to_perf;
 | 
						|
	u32 t_quiet_to_balanced;
 | 
						|
	u32 t_balanced_to_quiet;
 | 
						|
	u32 t_perf_to_balanced;
 | 
						|
	u32 t_turbo_to_perf;
 | 
						|
	struct apmf_cnqf_power_set ps[APMF_CNQF_MAX];
 | 
						|
} __packed;
 | 
						|
 | 
						|
/* Core Layer */
 | 
						|
int apmf_acpi_init(struct amd_pmf_dev *pmf_dev);
 | 
						|
void apmf_acpi_deinit(struct amd_pmf_dev *pmf_dev);
 | 
						|
int is_apmf_func_supported(struct amd_pmf_dev *pdev, unsigned long index);
 | 
						|
int amd_pmf_send_cmd(struct amd_pmf_dev *dev, u8 message, bool get, u32 arg, u32 *data);
 | 
						|
int amd_pmf_init_metrics_table(struct amd_pmf_dev *dev);
 | 
						|
int amd_pmf_get_power_source(void);
 | 
						|
int apmf_install_handler(struct amd_pmf_dev *pmf_dev);
 | 
						|
int apmf_os_power_slider_update(struct amd_pmf_dev *dev, u8 flag);
 | 
						|
 | 
						|
/* SPS Layer */
 | 
						|
int amd_pmf_get_pprof_modes(struct amd_pmf_dev *pmf);
 | 
						|
void amd_pmf_update_slider(struct amd_pmf_dev *dev, bool op, int idx,
 | 
						|
			   struct amd_pmf_static_slider_granular *table);
 | 
						|
int amd_pmf_init_sps(struct amd_pmf_dev *dev);
 | 
						|
void amd_pmf_deinit_sps(struct amd_pmf_dev *dev);
 | 
						|
int apmf_get_static_slider_granular(struct amd_pmf_dev *pdev,
 | 
						|
				    struct apmf_static_slider_granular_output *output);
 | 
						|
bool is_pprof_balanced(struct amd_pmf_dev *pmf);
 | 
						|
int amd_pmf_power_slider_update_event(struct amd_pmf_dev *dev);
 | 
						|
 | 
						|
 | 
						|
int apmf_update_fan_idx(struct amd_pmf_dev *pdev, bool manual, u32 idx);
 | 
						|
int amd_pmf_set_sps_power_limits(struct amd_pmf_dev *pmf);
 | 
						|
 | 
						|
/* Auto Mode Layer */
 | 
						|
int apmf_get_auto_mode_def(struct amd_pmf_dev *pdev, struct apmf_auto_mode *data);
 | 
						|
void amd_pmf_init_auto_mode(struct amd_pmf_dev *dev);
 | 
						|
void amd_pmf_deinit_auto_mode(struct amd_pmf_dev *dev);
 | 
						|
void amd_pmf_trans_automode(struct amd_pmf_dev *dev, int socket_power, ktime_t time_elapsed_ms);
 | 
						|
int apmf_get_sbios_requests(struct amd_pmf_dev *pdev, struct apmf_sbios_req *req);
 | 
						|
 | 
						|
void amd_pmf_update_2_cql(struct amd_pmf_dev *dev, bool is_cql_event);
 | 
						|
int amd_pmf_reset_amt(struct amd_pmf_dev *dev);
 | 
						|
void amd_pmf_handle_amt(struct amd_pmf_dev *dev);
 | 
						|
 | 
						|
/* CnQF Layer */
 | 
						|
int apmf_get_dyn_slider_def_ac(struct amd_pmf_dev *pdev, struct apmf_dyn_slider_output *data);
 | 
						|
int apmf_get_dyn_slider_def_dc(struct amd_pmf_dev *pdev, struct apmf_dyn_slider_output *data);
 | 
						|
int amd_pmf_init_cnqf(struct amd_pmf_dev *dev);
 | 
						|
void amd_pmf_deinit_cnqf(struct amd_pmf_dev *dev);
 | 
						|
int amd_pmf_trans_cnqf(struct amd_pmf_dev *dev, int socket_power, ktime_t time_lapsed_ms);
 | 
						|
extern const struct attribute_group cnqf_feature_attribute_group;
 | 
						|
 | 
						|
#endif /* PMF_H */
 |