Merge "ARM: dts: msm: Enable CXIP LM feature for sdm660"

This commit is contained in:
Linux Build Service Account 2017-02-02 12:31:29 -08:00 committed by Gerrit - the friendly Code Review server
commit 00b5ea2384
3 changed files with 195 additions and 2 deletions

View file

@ -105,7 +105,9 @@ Optional properties
- clock-names: The list of clocks needed for thermal module. Must be
- "osm" for LMH DCVS
- clocks: The phandle to the clocks.
- qcom,cxip-lm-enable: If this optional property is defined with a non zero value,
it enables CXIP_LM hardware feature. If value is zero,
it disables CXIP_LM hardware feature.
Optional child nodes
- qcom,pmic-opt-curr-temp: Threshold temperature for requesting optimum current (request
dual phase) for rails with PMIC, in degC. If this property exists,

View file

@ -728,7 +728,7 @@
clock-names = "osm";
clocks = <&clock_cpu PWRCL_CLK>;
qcom,cxip-lm-enable = <1>;
qcom,vdd-restriction-temp = <5>;
qcom,vdd-restriction-temp-hysteresis = <10>;

View file

@ -49,6 +49,7 @@
#include <linux/suspend.h>
#include <linux/uaccess.h>
#include <linux/uio_driver.h>
#include <linux/io.h>
#include <asm/cacheflush.h>
@ -88,6 +89,20 @@
#define HOTPLUG_RETRY_INTERVAL_MS 100
#define UIO_VERSION "1.0"
#define CXIP_LM_BASE_ADDRESS 0x1FE5000
#define CXIP_LM_ADDRESS_SIZE 0x68
#define CXIP_LM_VOTE_STATUS 0x40
#define CXIP_LM_BYPASS 0x44
#define CXIP_LM_VOTE_CLEAR 0x48
#define CXIP_LM_VOTE_SET 0x4c
#define CXIP_LM_FEATURE_EN 0x50
#define CXIP_LM_DISABLE_VAL 0x0
#define CXIP_LM_BYPASS_VAL 0xFF00
#define CXIP_LM_THERM_VOTE_VAL 0x80
#define CXIP_LM_THERM_SENS_ID 8
#define CXIP_LM_THERM_SENS_HIGH 90
#define CXIP_LM_THERM_SENS_LOW 75
#define VALIDATE_AND_SET_MASK(_node, _key, _mask, _cpu) \
do { \
if (of_property_read_bool(_node, _key)) \
@ -179,6 +194,7 @@ static bool gfx_warm_phase_ctrl_enabled;
static bool cx_phase_ctrl_enabled;
static bool vdd_mx_enabled;
static bool therm_reset_enabled;
static bool cxip_lm_enabled;
static bool online_core;
static bool cluster_info_probed;
static bool cluster_info_nodes_called;
@ -207,6 +223,7 @@ static bool tsens_temp_print;
static uint32_t bucket;
static cpumask_t throttling_mask;
static int tsens_scaling_factor = SENSOR_SCALING_FACTOR;
static void *cxip_lm_reg_base;
static LIST_HEAD(devices_list);
static LIST_HEAD(thresholds_list);
@ -301,6 +318,7 @@ enum msm_thresh_list {
MSM_GFX_PHASE_CTRL_HOT,
MSM_OCR,
MSM_VDD_MX_RESTRICTION,
MSM_THERM_CXIP_LM,
MSM_LIST_MAX_NR,
};
@ -495,6 +513,9 @@ static ssize_t thermal_config_debugfs_write(struct file *file,
} \
} while (0)
#define CXIP_LM_CLIENTS_STATUS() \
readl_relaxed(cxip_lm_reg_base + CXIP_LM_VOTE_STATUS)
static void uio_init(struct platform_device *pdev)
{
int ret = 0;
@ -2895,6 +2916,76 @@ static void therm_reset_notify(struct therm_threshold *thresh_data)
thresh_data->threshold);
}
static void cxip_lm_therm_vote_apply(bool vote)
{
static bool prev_vote;
if (prev_vote == vote)
return;
prev_vote = vote;
writel_relaxed(CXIP_LM_THERM_VOTE_VAL,
cxip_lm_reg_base +
(vote ? CXIP_LM_VOTE_SET : CXIP_LM_VOTE_CLEAR));
pr_debug("%s vote for cxip_lm. Agg.vote:0x%x\n",
vote ? "Applied" : "Cleared", CXIP_LM_CLIENTS_STATUS());
}
static int do_cxip_lm(void)
{
int temp = 0, ret = 0;
if (!cxip_lm_enabled)
return ret;
ret = therm_get_temp(
thresh[MSM_THERM_CXIP_LM].thresh_list->sensor_id,
thresh[MSM_THERM_CXIP_LM].thresh_list->id_type,
&temp);
if (ret) {
pr_err("Unable to read TSENS sensor:%d, err:%d\n",
thresh[MSM_THERM_CXIP_LM].thresh_list->sensor_id, ret);
return ret;
}
if (temp >= CXIP_LM_THERM_SENS_HIGH)
cxip_lm_therm_vote_apply(true);
else if (temp <= CXIP_LM_THERM_SENS_LOW)
cxip_lm_therm_vote_apply(false);
return ret;
}
static void therm_cxip_lm_notify(struct therm_threshold *trig_thresh)
{
if (!cxip_lm_enabled)
return;
if (!trig_thresh) {
pr_err("Invalid input\n");
return;
}
switch (trig_thresh->trip_triggered) {
case THERMAL_TRIP_CONFIGURABLE_HI:
cxip_lm_therm_vote_apply(true);
break;
case THERMAL_TRIP_CONFIGURABLE_LOW:
cxip_lm_therm_vote_apply(false);
break;
default:
pr_err("Invalid trip type\n");
break;
}
if (trig_thresh->cur_state != trig_thresh->trip_triggered) {
sensor_mgr_set_threshold(trig_thresh->sensor_id,
trig_thresh->threshold);
trig_thresh->cur_state = trig_thresh->trip_triggered;
}
}
static void retry_hotplug(struct work_struct *work)
{
mutex_lock(&core_control_mutex);
@ -3524,6 +3615,7 @@ static void check_temp(struct work_struct *work)
goto reschedule;
}
do_core_control(temp);
do_cxip_lm();
do_vdd_mx();
do_psm();
do_gfx_phase_cond();
@ -4560,6 +4652,13 @@ static void thermal_monitor_init(void)
!(convert_to_zone_id(&thresh[MSM_VDD_MX_RESTRICTION])))
therm_set_threshold(&thresh[MSM_VDD_MX_RESTRICTION]);
if (cxip_lm_enabled &&
!(convert_to_zone_id(&thresh[MSM_THERM_CXIP_LM]))) {
/* To handle if temp > HIGH */
do_cxip_lm();
therm_set_threshold(&thresh[MSM_THERM_CXIP_LM]);
}
init_exit:
return;
}
@ -6229,6 +6328,74 @@ fetch_mitig_exit:
return err;
}
static void thermal_cxip_lm_disable(void)
{
THERM_MITIGATION_DISABLE(cxip_lm_enabled, MSM_THERM_CXIP_LM);
cxip_lm_therm_vote_apply(false);
}
static int probe_cxip_lm(struct device_node *node,
struct msm_thermal_data *data,
struct platform_device *pdev)
{
char *key = NULL;
int ret = 0;
u32 val = 0;
key = "qcom,cxip-lm-enable";
ret = of_property_read_u32(node, key, &val);
if (ret) {
cxip_lm_enabled = false;
return -EINVAL;
}
cxip_lm_enabled = val ? true : false;
cxip_lm_reg_base = devm_ioremap(&pdev->dev,
CXIP_LM_BASE_ADDRESS, CXIP_LM_ADDRESS_SIZE);
if (!cxip_lm_reg_base) {
pr_err("cxip_lm reg remap failed\n");
ret = -ENOMEM;
goto PROBE_CXIP_LM_EXIT;
}
/* If it is disable request, disable and exit */
if (!cxip_lm_enabled) {
writel_relaxed(CXIP_LM_DISABLE_VAL,
cxip_lm_reg_base + CXIP_LM_FEATURE_EN);
devm_ioremap_release(&pdev->dev, cxip_lm_reg_base);
return 0;
};
/* Set bypass clients bits */
writel_relaxed(CXIP_LM_BYPASS_VAL, cxip_lm_reg_base + CXIP_LM_BYPASS);
ret = sensor_mgr_init_threshold(&thresh[MSM_THERM_CXIP_LM],
CXIP_LM_THERM_SENS_ID, CXIP_LM_THERM_SENS_HIGH,
CXIP_LM_THERM_SENS_LOW, therm_cxip_lm_notify);
if (ret) {
pr_err("cxip_lm sensor init failed\n");
goto PROBE_CXIP_LM_EXIT;
}
snprintf(mit_config[MSM_THERM_CXIP_LM].config_name,
MAX_DEBUGFS_CONFIG_LEN, "cxip_lm");
mit_config[MSM_THERM_CXIP_LM].disable_config
= thermal_cxip_lm_disable;
PROBE_CXIP_LM_EXIT:
if (ret) {
if (cxip_lm_reg_base)
devm_ioremap_release(&pdev->dev,
cxip_lm_reg_base);
dev_info(&pdev->dev,
"%s:Failed reading node=%s, key=%s err=%d. KTM continues\n",
__func__, node->full_name, key, ret);
cxip_lm_enabled = false;
}
return ret;
}
static void probe_sensor_info(struct device_node *node,
struct msm_thermal_data *data, struct platform_device *pdev)
{
@ -6997,6 +7164,19 @@ static void thermal_phase_ctrl_config_read(struct seq_file *m, void *data)
msm_thermal_info.gfx_sensor);
}
static void thermal_cxip_lm_config_read(struct seq_file *m, void *data)
{
if (cxip_lm_enabled) {
seq_puts(m, "\n-----CX IPEAK LM-----\n");
seq_printf(m, "threshold:%d degC\n",
CXIP_LM_THERM_SENS_HIGH);
seq_printf(m, "threshold clear:%d degC\n",
CXIP_LM_THERM_SENS_LOW);
seq_printf(m, "tsens sensor:tsens_tz_sensor%d\n",
CXIP_LM_THERM_SENS_ID);
}
}
static void thermal_disable_all_mitigation(void)
{
thermal_cpu_freq_mit_disable();
@ -7009,6 +7189,7 @@ static void thermal_disable_all_mitigation(void)
thermal_cx_phase_ctrl_mit_disable();
thermal_gfx_phase_warm_ctrl_mit_disable();
thermal_gfx_phase_crit_ctrl_mit_disable();
thermal_cxip_lm_disable();
}
static void enable_config(int config_id)
@ -7035,6 +7216,9 @@ static void enable_config(int config_id)
case MSM_VDD_MX_RESTRICTION:
vdd_mx_enabled = 1;
break;
case MSM_THERM_CXIP_LM:
cxip_lm_enabled = 1;
break;
case MSM_LIST_MAX_NR + HOTPLUG_CONFIG:
hotplug_enabled = 1;
break;
@ -7138,6 +7322,7 @@ static int thermal_config_debugfs_read(struct seq_file *m, void *data)
thermal_psm_config_read(m, data);
thermal_ocr_config_read(m, data);
thermal_phase_ctrl_config_read(m, data);
thermal_cxip_lm_config_read(m, data);
return 0;
}
@ -7226,6 +7411,7 @@ static int msm_thermal_dev_probe(struct platform_device *pdev)
probe_cx_phase_ctrl(node, &data, pdev);
probe_gfx_phase_ctrl(node, &data, pdev);
probe_therm_reset(node, &data, pdev);
probe_cxip_lm(node, &data, pdev);
update_cpu_topology(&pdev->dev);
ret = fetch_cpu_mitigaiton_info(&data, pdev);
if (ret) {
@ -7305,6 +7491,11 @@ static int msm_thermal_dev_exit(struct platform_device *inp_dev)
&thresh[MSM_VDD_MX_RESTRICTION]);
kfree(thresh[MSM_VDD_MX_RESTRICTION].thresh_list);
}
if (cxip_lm_enabled) {
sensor_mgr_remove_threshold(
&thresh[MSM_THERM_CXIP_LM]);
kfree(thresh[MSM_THERM_CXIP_LM].thresh_list);
}
kfree(thresh);
thresh = NULL;
}