Merge branches 'misc' and 'soc' of .git into next

This commit is contained in:
Zhang Rui 2014-01-03 22:55:04 +08:00
commit 8c59ecb5c1
4 changed files with 37 additions and 1 deletions

View File

@ -8,10 +8,14 @@ Required properties:
calibration data, e.g. OCOTP on imx6q. The details about calibration data calibration data, e.g. OCOTP on imx6q. The details about calibration data
can be found in SoC Reference Manual. can be found in SoC Reference Manual.
Optional properties:
- clocks : thermal sensor's clock source.
Example: Example:
tempmon { tempmon {
compatible = "fsl,imx6q-tempmon"; compatible = "fsl,imx6q-tempmon";
fsl,tempmon = <&anatop>; fsl,tempmon = <&anatop>;
fsl,tempmon-data = <&ocotp>; fsl,tempmon-data = <&ocotp>;
clocks = <&clks 172>;
}; };

View File

@ -7,6 +7,7 @@
* *
*/ */
#include <linux/clk.h>
#include <linux/cpu_cooling.h> #include <linux/cpu_cooling.h>
#include <linux/cpufreq.h> #include <linux/cpufreq.h>
#include <linux/delay.h> #include <linux/delay.h>
@ -73,6 +74,7 @@ struct imx_thermal_data {
unsigned long last_temp; unsigned long last_temp;
bool irq_enabled; bool irq_enabled;
int irq; int irq;
struct clk *thermal_clk;
}; };
static void imx_set_alarm_temp(struct imx_thermal_data *data, static void imx_set_alarm_temp(struct imx_thermal_data *data,
@ -457,6 +459,22 @@ static int imx_thermal_probe(struct platform_device *pdev)
return ret; return ret;
} }
data->thermal_clk = devm_clk_get(&pdev->dev, NULL);
if (IS_ERR(data->thermal_clk)) {
dev_warn(&pdev->dev, "failed to get thermal clk!\n");
} else {
/*
* Thermal sensor needs clk on to get correct value, normally
* we should enable its clk before taking measurement and disable
* clk after measurement is done, but if alarm function is enabled,
* hardware will auto measure the temperature periodically, so we
* need to keep the clk always on for alarm function.
*/
ret = clk_prepare_enable(data->thermal_clk);
if (ret)
dev_warn(&pdev->dev, "failed to enable thermal clk: %d\n", ret);
}
/* Enable measurements at ~ 10 Hz */ /* Enable measurements at ~ 10 Hz */
regmap_write(map, TEMPSENSE1 + REG_CLR, TEMPSENSE1_MEASURE_FREQ); regmap_write(map, TEMPSENSE1 + REG_CLR, TEMPSENSE1_MEASURE_FREQ);
measure_freq = DIV_ROUND_UP(32768, 10); /* 10 Hz */ measure_freq = DIV_ROUND_UP(32768, 10); /* 10 Hz */
@ -478,6 +496,8 @@ static int imx_thermal_remove(struct platform_device *pdev)
/* Disable measurements */ /* Disable measurements */
regmap_write(map, TEMPSENSE0 + REG_SET, TEMPSENSE0_POWER_DOWN); regmap_write(map, TEMPSENSE0 + REG_SET, TEMPSENSE0_POWER_DOWN);
if (!IS_ERR(data->thermal_clk))
clk_disable_unprepare(data->thermal_clk);
thermal_zone_device_unregister(data->tz); thermal_zone_device_unregister(data->tz);
cpufreq_cooling_unregister(data->cdev); cpufreq_cooling_unregister(data->cdev);

View File

@ -206,6 +206,15 @@ static void find_target_mwait(void)
} }
static bool has_pkg_state_counter(void)
{
u64 tmp;
return !rdmsrl_safe(MSR_PKG_C2_RESIDENCY, &tmp) ||
!rdmsrl_safe(MSR_PKG_C3_RESIDENCY, &tmp) ||
!rdmsrl_safe(MSR_PKG_C6_RESIDENCY, &tmp) ||
!rdmsrl_safe(MSR_PKG_C7_RESIDENCY, &tmp);
}
static u64 pkg_state_counter(void) static u64 pkg_state_counter(void)
{ {
u64 val; u64 val;
@ -500,7 +509,7 @@ static int start_power_clamp(void)
struct task_struct *thread; struct task_struct *thread;
/* check if pkg cstate counter is completely 0, abort in this case */ /* check if pkg cstate counter is completely 0, abort in this case */
if (!pkg_state_counter()) { if (!has_pkg_state_counter()) {
pr_err("pkg cstate counter not functional, abort\n"); pr_err("pkg cstate counter not functional, abort\n");
return -EINVAL; return -EINVAL;
} }

View File

@ -781,6 +781,9 @@ emul_temp_store(struct device *dev, struct device_attribute *attr,
ret = tz->ops->set_emul_temp(tz, temperature); ret = tz->ops->set_emul_temp(tz, temperature);
} }
if (!ret)
thermal_zone_device_update(tz);
return ret ? ret : count; return ret ? ret : count;
} }
static DEVICE_ATTR(emul_temp, S_IWUSR, NULL, emul_temp_store); static DEVICE_ATTR(emul_temp, S_IWUSR, NULL, emul_temp_store);