Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 85947c7f authored by Ram Chandrasekar's avatar Ram Chandrasekar
Browse files

msm: thermal: Add support for emergency frequency mitigation



Add emergency frequency mitigation support to Kernel Thermal
Monitor. This feature enables KTM to mitigate the cpu's max
frequency when the temperature crosses the preset threshold.

CRs-Fixed: 538981
Change-Id: Ifb5b60b11c584d897117832156bb11190b743b1d
Signed-off-by: default avatarRam Chandrasekar <rkumbako@codeaurora.org>
parent 2f9d4dc1
Loading
Loading
Loading
Loading
+27 −0
Original line number Diff line number Diff line
@@ -43,6 +43,29 @@ Optional properties
- qcpm,cpu-sensors:     List of type names in thermal zone device struct which maps
			to cpu0, cpu1, cpu2, cpu3 in sequence depending on how many
			cpus there are.
- qcom,freq-mitigation-temp: Threshold temperature to mitigate
			the CPU max frequency in degC. This will be
			used when polling based frequency control is disabled.
			The difference between freq-mitigation-temp
			and limit-temp is that limit-temp is used during
			early boot prior to thermal_sys being available for registering
			temperature thresholds. Also, this emergency frequency
			mitigation is a single step frequency mitigation to a predefined value
			as opposed to the step by step frequency mitigation during boot-up.
- qcom,freq-mitigation-temp-hysteresis: Degrees C below which thermal will not mitigate the
			cpu max frequency.
- qcom,freq-mitigation-value: The frequency value (in kHz) to which the thermal
			should mitigate the CPU, when the freq-mitigation-temp
			threshold is reached.
- qcom,freq-mitigation-control-mask: The frequency mitigation bitmask that will be
			used to determine if KTM should do emergency frequency
			mitigation for a core or not. A mask of 0x00 indicates the
			mitigation is disabled for all the cores and a mask of 0x05
			indicates this mitigation is enabled for cpu-0 and cpu-2.
			Note: For KTM's frequency mitigation to work, the data for all the
			above four properties (qcom,freq-mitigation-temp; qcom,
			freq-mitigation-temp-hysteresis; qcom,freq-mitigation-value and
			qcom,freq-mitigation-control-mask) should be populated.
- qcom,vdd-restriction-temp: When temperature is below this threshold, will
			enable vdd restriction which will set higher voltage on
			key voltage rails, in degC.
@@ -97,6 +120,10 @@ Example:
		qcom,hotplug-temp-hysteresis = <20>;
		qcom,cpu-sensors = "tsens_tz_sensor5", "tsens_tz_sensor6",
				"tsens_tz_sensor7", "tsens_tz_sensor8";
		qcom,freq-mitigation-temp = <110>;
		qcom,freq-mitigation-temp-hysteresis = <20>;
		qcom,freq-mitigation-value = <960000>;
		qcom,freq-mitigation-control-mask = <0x01>;
		qcom,pmic-sw-mode-temp = <90>;
		qcom,pmic-sw-mode-temp-hysteresis = <80>;
		qcom,pmic-sw-mode-regs = "vdd-dig";
+271 −79
Original line number Diff line number Diff line
@@ -40,8 +40,6 @@
#define MAX_THRESHOLD 2

static struct msm_thermal_data msm_thermal_info;
static uint32_t limited_max_freq = UINT_MAX;
static uint32_t limited_min_freq;
static struct delayed_work check_temp_work;
static bool core_control_enabled;
static uint32_t cpus_offlined;
@@ -52,7 +50,9 @@ static struct kobject *tt_kobj;
static struct kobject *cc_kobj;
static struct work_struct timer_work;
static struct task_struct *hotplug_task;
static struct task_struct *freq_mitigation_task;
static struct completion hotplug_notify_complete;
static struct completion freq_mitigation_complete;

static int enabled;
static int rails_cnt;
@@ -70,18 +70,32 @@ static bool vdd_rstr_probed;
static bool psm_enabled;
static bool psm_nodes_called;
static bool psm_probed;
static bool freq_mitigation_enabled;
static int *tsens_id_map;
static DEFINE_MUTEX(vdd_rstr_mutex);
static DEFINE_MUTEX(psm_mutex);
static uint32_t min_freq_limit;

enum thermal_threshold {
	HOTPLUG_THRESHOLD_HIGH,
	HOTPLUG_THRESHOLD_LOW,
	FREQ_THRESHOLD_HIGH,
	FREQ_THRESHOLD_LOW,
	THRESHOLD_MAX_NR,
};

struct cpu_info {
	uint32_t cpu;
	bool offline;
	bool user_offline;
	bool thresh_cleared;
	const char *sensor_type;
	uint32_t sensor_id;
	struct sensor_threshold thresh[MAX_THRESHOLD];
	bool offline;
	bool user_offline;
	bool hotplug_thresh_clear;
	struct sensor_threshold threshold[THRESHOLD_MAX_NR];
	bool max_freq;
	uint32_t limited_max_freq;
	uint32_t limited_min_freq;
	bool freq_thresh_clear;
};

struct rail {
@@ -162,11 +176,20 @@ static int msm_thermal_cpufreq_callback(struct notifier_block *nfb,
		unsigned long event, void *data)
{
	struct cpufreq_policy *policy = data;
	uint32_t max_freq_req = cpus[policy->cpu].limited_max_freq;
	uint32_t min_freq_req = cpus[policy->cpu].limited_min_freq;

	switch (event) {
	case CPUFREQ_INCOMPATIBLE:
		cpufreq_verify_within_limits(policy, limited_min_freq,
				limited_max_freq);
		pr_debug("%s: mitigating cpu %d to freq max: %u min: %u\n",
		KBUILD_MODNAME, policy->cpu, max_freq_req, min_freq_req);

		cpufreq_verify_within_limits(policy, min_freq_req,
			max_freq_req);

		if (max_freq_req < min_freq_req)
			pr_err("Invalid frequency request Max:%u Min:%u\n",
				max_freq_req, min_freq_req);
		break;
	}
	return NOTIFY_OK;
@@ -192,9 +215,17 @@ static int check_freq_table(void)
	return ret;
}

static void update_cpu_freq(int cpu)
{
	if (cpu_online(cpu)) {
		if (cpufreq_update_policy(cpu))
			pr_err("Unable to update policy for cpu:%d\n", cpu);
	}
}

static int update_cpu_min_freq_all(uint32_t min)
{
	int cpu = 0;
	uint32_t cpu = 0;
	int ret = 0;

	if (!freq_table_get) {
@@ -207,15 +238,17 @@ static int update_cpu_min_freq_all(uint32_t min)
	/* If min is larger than allowed max */
	min = min(min, table[limit_idx_high].frequency);

	limited_min_freq = min;

	if (freq_mitigation_task) {
		min_freq_limit = min;
		complete(&freq_mitigation_complete);
	} else {
		get_online_cpus();
	for_each_online_cpu(cpu) {
		if (cpufreq_update_policy(cpu))
			pr_info("%s: Unable to update policy for cpu:%d\n",
				KBUILD_MODNAME, cpu);
		for_each_possible_cpu(cpu) {
			cpus[cpu].limited_min_freq = min;
			update_cpu_freq(cpu);
		}
		put_online_cpus();
	}

	return ret;
}
@@ -606,27 +639,6 @@ fail:
	return ret;
}

static int update_cpu_max_freq(int cpu, uint32_t max_freq)
{
	int ret = 0;

	if (max_freq != UINT_MAX)
		pr_info("%s: Limiting cpu%d max frequency to %d\n",
				KBUILD_MODNAME, cpu, max_freq);
	else
		pr_info("%s: Max frequency reset for cpu%d\n",
				KBUILD_MODNAME, cpu);
	get_online_cpus();
	for_each_online_cpu(cpu) {
		if (cpufreq_update_policy(cpu))
			pr_info("%s: Unable to update policy for cpu:%d\n",
				KBUILD_MODNAME, cpu);
	}
	put_online_cpus();

	return ret;
}

static int set_and_activate_threshold(uint32_t sensor_id,
	struct sensor_threshold *threshold)
{
@@ -786,10 +798,11 @@ static __ref int do_hotplug(void *data)

		mutex_lock(&core_control_mutex);
		for_each_possible_cpu(cpu) {
			if (cpus[cpu].thresh_cleared) {
			if (cpus[cpu].hotplug_thresh_clear) {
				set_threshold(cpus[cpu].sensor_id,
					cpus[cpu].thresh);
				cpus[cpu].thresh_cleared = false;
				&cpus[cpu].threshold[HOTPLUG_THRESHOLD_HIGH]);

				cpus[cpu].hotplug_thresh_clear = false;
			}
			if (cpus[cpu].offline || cpus[cpu].user_offline)
				mask |= BIT(cpu);
@@ -913,14 +926,14 @@ exit:

static void do_freq_control(long temp)
{
	int cpu = 0;
	uint32_t max_freq = limited_max_freq;
	uint32_t cpu = 0;
	uint32_t max_freq = cpus[cpu].limited_max_freq;

	if (temp >= msm_thermal_info.limit_temp_degC) {
		if (limit_idx == limit_idx_low)
			return;

		limit_idx -= msm_thermal_info.freq_step;
		limit_idx -= msm_thermal_info.bootup_freq_step;
		if (limit_idx < limit_idx_low)
			limit_idx = limit_idx_low;
		max_freq = table[limit_idx].frequency;
@@ -929,7 +942,7 @@ static void do_freq_control(long temp)
		if (limit_idx == limit_idx_high)
			return;

		limit_idx += msm_thermal_info.freq_step;
		limit_idx += msm_thermal_info.bootup_freq_step;
		if (limit_idx >= limit_idx_high) {
			limit_idx = limit_idx_high;
			max_freq = UINT_MAX;
@@ -937,16 +950,18 @@ static void do_freq_control(long temp)
			max_freq = table[limit_idx].frequency;
	}

	if (max_freq == limited_max_freq)
	if (max_freq == cpus[cpu].limited_max_freq)
		return;

	limited_max_freq = max_freq;
	/* Update new limits */
	get_online_cpus();
	for_each_possible_cpu(cpu) {
		if (!(msm_thermal_info.freq_control_mask & BIT(cpu)))
		if (!(msm_thermal_info.bootup_freq_control_mask & BIT(cpu)))
			continue;
		update_cpu_max_freq(cpu, max_freq);
		cpus[cpu].limited_max_freq = max_freq;
		update_cpu_freq(cpu);
	}
	put_online_cpus();
}

static void check_temp(struct work_struct *work)
@@ -986,7 +1001,7 @@ reschedule:
static int __ref msm_thermal_cpu_callback(struct notifier_block *nfb,
		unsigned long action, void *hcpu)
{
	unsigned int cpu = (unsigned long)hcpu;
	uint32_t cpu = (uint32_t)hcpu;

	if (action == CPU_UP_PREPARE || action == CPU_UP_PREPARE_FROZEN) {
		if (core_control_enabled &&
@@ -1058,7 +1073,7 @@ static int hotplug_notify(enum thermal_trip_type type, int temp, void *data)
		break;
	}
	if (hotplug_task) {
		cpu_node->thresh_cleared = true;
		cpu_node->hotplug_thresh_clear = true;
		complete(&hotplug_notify_complete);
	} else
		pr_err("%s: Hotplug task is not initialized\n", KBUILD_MODNAME);
@@ -1069,7 +1084,7 @@ static int hotplug_init_cpu_offlined(void)
{
	struct tsens_device tsens_dev;
	long temp = 0;
	int cpu = 0;
	uint32_t cpu = 0;

	mutex_lock(&core_control_mutex);
	for_each_possible_cpu(cpu) {
@@ -1102,29 +1117,29 @@ static int hotplug_init_cpu_offlined(void)

static void hotplug_init(void)
{
	int cpu = 0;
	uint32_t cpu = 0;
	struct sensor_threshold *hi_thresh = NULL, *low_thresh = NULL;

	if (hotplug_task)
		return;

	for_each_possible_cpu(cpu) {
		cpus[cpu].cpu = (uint32_t)cpu;
		cpus[cpu].thresh_cleared = false;
		cpus[cpu].sensor_id =
			sensor_get_id((char *)cpus[cpu].sensor_type);
		if (!(msm_thermal_info.core_control_mask & BIT(cpus[cpu].cpu)))
			continue;
		cpus[cpu].thresh[0].temp = msm_thermal_info.hotplug_temp_degC;
		cpus[cpu].thresh[0].trip = THERMAL_TRIP_CONFIGURABLE_HI;
		cpus[cpu].thresh[0].notify = hotplug_notify;
		cpus[cpu].thresh[0].data = (void *)&cpus[cpu];

		cpus[cpu].thresh[1].temp = msm_thermal_info.hotplug_temp_degC -
		hi_thresh = &cpus[cpu].threshold[HOTPLUG_THRESHOLD_HIGH];
		low_thresh = &cpus[cpu].threshold[HOTPLUG_THRESHOLD_LOW];
		hi_thresh->temp = msm_thermal_info.hotplug_temp_degC;
		hi_thresh->trip = THERMAL_TRIP_CONFIGURABLE_HI;
		low_thresh->temp = msm_thermal_info.hotplug_temp_degC -
				msm_thermal_info.hotplug_temp_hysteresis_degC;
		cpus[cpu].thresh[1].trip = THERMAL_TRIP_CONFIGURABLE_LOW;
		cpus[cpu].thresh[1].notify = hotplug_notify;
		cpus[cpu].thresh[1].data = (void *)&cpus[cpu];
		set_threshold(cpus[cpu].sensor_id, cpus[cpu].thresh);
		low_thresh->trip = THERMAL_TRIP_CONFIGURABLE_LOW;
		hi_thresh->notify = low_thresh->notify = hotplug_notify;
		hi_thresh->data = low_thresh->data = (void *)&cpus[cpu];

		set_threshold(cpus[cpu].sensor_id, hi_thresh);
	}
	init_completion(&hotplug_notify_complete);
	hotplug_task = kthread_run(do_hotplug, NULL, "msm_thermal:hotplug");
@@ -1141,6 +1156,124 @@ static void hotplug_init(void)
		kthread_stop(hotplug_task);
}

static __ref int do_freq_mitigation(void *data)
{
	int ret = 0;
	uint32_t cpu = 0, max_freq_req = 0;

	while (!kthread_should_stop()) {
		wait_for_completion(&freq_mitigation_complete);
		INIT_COMPLETION(freq_mitigation_complete);

		get_online_cpus();
		for_each_possible_cpu(cpu) {
			max_freq_req = (cpus[cpu].max_freq) ?
					msm_thermal_info.freq_limit :
					UINT_MAX;

			if ((max_freq_req == cpus[cpu].limited_max_freq)
				&& (min_freq_limit ==
				cpus[cpu].limited_min_freq))
				goto reset_threshold;

			cpus[cpu].limited_max_freq = max_freq_req;
			cpus[cpu].limited_min_freq = min_freq_limit;
			update_cpu_freq(cpu);
reset_threshold:
			if (cpus[cpu].freq_thresh_clear) {
				set_threshold(cpus[cpu].sensor_id,
				&cpus[cpu].threshold[FREQ_THRESHOLD_HIGH]);

				cpus[cpu].freq_thresh_clear = false;
			}
		}
		put_online_cpus();
	}
	return ret;
}

static int freq_mitigation_notify(enum thermal_trip_type type,
	int temp, void *data)
{
	struct cpu_info *cpu_node = (struct cpu_info *) data;

	pr_debug("%s: %s reached temp threshold: %d\n", KBUILD_MODNAME,
		cpu_node->sensor_type, temp);

	if (!(msm_thermal_info.freq_mitig_control_mask &
		BIT(cpu_node->cpu)))
		return 0;

	switch (type) {
	case THERMAL_TRIP_CONFIGURABLE_HI:
		if (!cpu_node->max_freq) {
			pr_info("%s: Mitigating cpu %d frequency to %d\n",
				KBUILD_MODNAME, cpu_node->cpu,
				msm_thermal_info.freq_limit);

			cpu_node->max_freq = true;
		}
		break;
	case THERMAL_TRIP_CONFIGURABLE_LOW:
		if (cpu_node->max_freq) {
			pr_info("%s: Removing frequency mitigation for cpu%d\n",
				KBUILD_MODNAME, cpu_node->cpu);

			cpu_node->max_freq = false;
		}
		break;
	default:
		break;
	}

	if (freq_mitigation_task) {
		cpu_node->freq_thresh_clear = true;
		complete(&freq_mitigation_complete);
	} else {
		pr_err("%s: Frequency mitigation task is not initialized\n",
			KBUILD_MODNAME);
	}

	return 0;
}

static void freq_mitigation_init(void)
{
	uint32_t cpu = 0;
	struct sensor_threshold *hi_thresh = NULL, *low_thresh = NULL;

	if (!freq_mitigation_enabled || freq_mitigation_task)
		return;

	for_each_possible_cpu(cpu) {
		if (!(msm_thermal_info.freq_mitig_control_mask & BIT(cpu)))
			continue;
		hi_thresh = &cpus[cpu].threshold[FREQ_THRESHOLD_HIGH];
		low_thresh = &cpus[cpu].threshold[FREQ_THRESHOLD_LOW];

		hi_thresh->temp = msm_thermal_info.freq_mitig_temp_degc;
		hi_thresh->trip = THERMAL_TRIP_CONFIGURABLE_HI;
		low_thresh->temp = msm_thermal_info.freq_mitig_temp_degc -
			msm_thermal_info.freq_mitig_temp_hysteresis_degc;
		low_thresh->trip = THERMAL_TRIP_CONFIGURABLE_LOW;
		hi_thresh->notify = low_thresh->notify =
			freq_mitigation_notify;
		hi_thresh->data = low_thresh->data = (void *)&cpus[cpu];

		set_threshold(cpus[cpu].sensor_id, hi_thresh);
	}

	init_completion(&freq_mitigation_complete);
	freq_mitigation_task = kthread_run(do_freq_mitigation, NULL,
		"msm_thermal:freq_mitig");

	if (IS_ERR(freq_mitigation_task)) {
		pr_err("%s: Failed to create frequency mitigation thread\n",
				KBUILD_MODNAME);
		return;
	}
}

/*
 * We will reset the cpu frequencies limits here. The core online/offline
 * status will be carried over to the process stopping the msm_thermal, as
@@ -1148,21 +1281,20 @@ static void hotplug_init(void)
 */
static void __ref disable_msm_thermal(void)
{
	int cpu = 0;
	uint32_t cpu = 0;

	/* make sure check_temp is no longer running */
	cancel_delayed_work(&check_temp_work);
	flush_scheduled_work();

	if (limited_max_freq == UINT_MAX)
		return;

	limited_max_freq = UINT_MAX;
	get_online_cpus();
	for_each_online_cpu(cpu) {
		if (cpufreq_update_policy(cpu))
			pr_info("%s: Unable to update policy for cpu:%d\n",
				KBUILD_MODNAME, cpu);
	for_each_possible_cpu(cpu) {
		if (cpus[cpu].limited_max_freq == UINT_MAX &&
			cpus[cpu].limited_min_freq == 0)
			continue;
		cpus[cpu].limited_max_freq = UINT_MAX;
		cpus[cpu].limited_min_freq = 0;
		update_cpu_freq(cpu);
	}
	put_online_cpus();
}
@@ -1175,6 +1307,7 @@ static int __ref set_enabled(const char *val, const struct kernel_param *kp)
	if (!enabled) {
		disable_msm_thermal();
		hotplug_init();
		freq_mitigation_init();
	} else
		pr_info("%s: no action for enabled = %d\n",
			KBUILD_MODNAME, enabled);
@@ -1242,7 +1375,7 @@ static ssize_t __ref store_cpus_offlined(struct kobject *kobj,
{
	int ret = 0;
	uint32_t val = 0;
	int cpu;
	uint32_t cpu;

	mutex_lock(&core_control_mutex);
	ret = kstrtouint(buf, 10, &val);
@@ -1407,6 +1540,7 @@ failed:
int msm_thermal_init(struct msm_thermal_data *pdata)
{
	int ret = 0;
	uint32_t cpu;

	BUG_ON(!pdata);
	tsens_get_max_sensor_num(&max_tsens_num);
@@ -1418,7 +1552,10 @@ int msm_thermal_init(struct msm_thermal_data *pdata)
		return -EINVAL;

	enabled = 1;

	for_each_possible_cpu(cpu) {
		cpus[cpu].limited_max_freq = UINT_MAX;
		cpus[cpu].limited_min_freq = 0;
	}
	ret = cpufreq_register_notifier(&msm_thermal_cpufreq_notifier,
			CPUFREQ_POLICY_NOTIFIER);
	if (ret)
@@ -1839,9 +1976,9 @@ static int probe_cc(struct device_node *node, struct msm_thermal_data *data,
		struct platform_device *pdev)
{
	char *key = NULL;
	int cpu_cnt = 0;
	uint32_t cpu_cnt = 0;
	int ret = 0;
	int cpu = 0;
	uint32_t cpu = 0;

	key = "qcom,core-limit-temp";
	ret = of_property_read_u32(node, key, &data->core_limit_temp_degC);
@@ -1880,6 +2017,7 @@ static int probe_cc(struct device_node *node, struct msm_thermal_data *data,
		cpus[cpu].cpu = cpu;
		cpus[cpu].offline = 0;
		cpus[cpu].user_offline = 0;
		cpus[cpu].hotplug_thresh_clear = false;
		ret = of_property_read_string_index(node, key, cpu,
				&cpus[cpu].sensor_type);
		if (ret)
@@ -1900,6 +2038,53 @@ read_node_fail:
	return ret;
}

static int probe_freq_mitigation(struct device_node *node,
		struct msm_thermal_data *data,
		struct platform_device *pdev)
{
	char *key = NULL;
	int ret = 0;
	uint32_t cpu;

	key = "qcom,freq-mitigation-temp";
	ret = of_property_read_u32(node, key, &data->freq_mitig_temp_degc);
	if (ret)
		goto PROBE_FREQ_EXIT;

	key = "qcom,freq-mitigation-temp-hysteresis";
	ret = of_property_read_u32(node, key,
		&data->freq_mitig_temp_hysteresis_degc);
	if (ret)
		goto PROBE_FREQ_EXIT;

	key = "qcom,freq-mitigation-value";
	ret = of_property_read_u32(node, key, &data->freq_limit);
	if (ret)
		goto PROBE_FREQ_EXIT;

	key = "qcom,freq-mitigation-control-mask";
	ret = of_property_read_u32(node, key, &data->freq_mitig_control_mask);
	if (ret)
		goto PROBE_FREQ_EXIT;

	freq_mitigation_enabled = 1;
	for_each_possible_cpu(cpu) {
		cpus[cpu].max_freq = false;
		cpus[cpu].limited_max_freq = UINT_MAX;
		cpus[cpu].limited_min_freq = 0;
		cpus[cpu].freq_thresh_clear = false;
	}

PROBE_FREQ_EXIT:
	if (ret) {
		dev_info(&pdev->dev,
			"%s:Failed reading node=%s, key=%s. KTM continues\n",
			__func__, node->full_name, key);
		freq_mitigation_enabled = 0;
	}
	return ret;
}

static int msm_thermal_dev_probe(struct platform_device *pdev)
{
	int ret = 0;
@@ -1930,14 +2115,16 @@ static int msm_thermal_dev_probe(struct platform_device *pdev)
		goto fail;

	key = "qcom,freq-step";
	ret = of_property_read_u32(node, key, &data.freq_step);
	ret = of_property_read_u32(node, key, &data.bootup_freq_step);
	if (ret)
		goto fail;

	key = "qcom,freq-control-mask";
	ret = of_property_read_u32(node, key, &data.freq_control_mask);
	ret = of_property_read_u32(node, key, &data.bootup_freq_control_mask);

	ret = probe_cc(node, &data, pdev);

	ret = probe_freq_mitigation(node, &data, pdev);
	/*
	 * Probe optional properties below. Call probe_psm before
	 * probe_vdd_rstr because rpm_regulator_get has to be called
@@ -1973,6 +2160,10 @@ fail:
	return ret;
}

static int msm_thermal_dev_exit(struct platform_device *inp_dev)
{
	return 0;
}

static struct of_device_id msm_thermal_match_table[] = {
	{.compatible = "qcom,msm-thermal"},
@@ -1986,6 +2177,7 @@ static struct platform_driver msm_thermal_device_driver = {
		.owner = THIS_MODULE,
		.of_match_table = msm_thermal_match_table,
	},
	.remove = msm_thermal_dev_exit,
};

int __init msm_thermal_device_init(void)
+6 −2
Original line number Diff line number Diff line
@@ -19,13 +19,17 @@ struct msm_thermal_data {
	uint32_t poll_ms;
	int32_t limit_temp_degC;
	int32_t temp_hysteresis_degC;
	uint32_t freq_step;
	uint32_t freq_control_mask;
	uint32_t bootup_freq_step;
	uint32_t bootup_freq_control_mask;
	int32_t core_limit_temp_degC;
	int32_t core_temp_hysteresis_degC;
	int32_t hotplug_temp_degC;
	int32_t hotplug_temp_hysteresis_degC;
	uint32_t core_control_mask;
	uint32_t freq_mitig_temp_degc;
	uint32_t freq_mitig_temp_hysteresis_degc;
	uint32_t freq_mitig_control_mask;
	uint32_t freq_limit;
	int32_t vdd_rstr_temp_degC;
	int32_t vdd_rstr_temp_hyst_degC;
	int32_t psm_temp_degC;