summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBai Ping <b51503@freescale.com>2015-05-22 22:39:11 +0800
committerBai Ping <b51503@freescale.com>2015-06-03 00:47:49 +0800
commit18d5b09e437c25b33eb43e7c65420b5cad26275f (patch)
treec1f41a440f98940d94e21f9dd6d2b13d25662c74
parent306a1b45c88451bcbe289bc911f3c52d1fd80862 (diff)
MLK-10960 thermal: imx: add a mutex to make sure tempmon setting changed safely
The busfreq notifier and thermal_zone updating run asynchronously. In some critical situaiton, the notifier callback may be interrupted by thermal_zone kthread, it will lead to the TEMPMON setting uncompleted when the get_temp function reads the temp sensor value. Signed-off-by: Bai Ping <b51503@freescale.com>
-rw-r--r--drivers/thermal/imx_thermal.c9
1 files changed, 9 insertions, 0 deletions
diff --git a/drivers/thermal/imx_thermal.c b/drivers/thermal/imx_thermal.c
index db37eec4f6e8..a5e72d7ac996 100644
--- a/drivers/thermal/imx_thermal.c
+++ b/drivers/thermal/imx_thermal.c
@@ -106,6 +106,7 @@ struct imx_thermal_data {
bool irq_enabled;
int irq;
struct clk *thermal_clk;
+ struct mutex mutex;
const struct thermal_soc_data *socdata;
};
@@ -144,6 +145,7 @@ static int imx_get_temp(struct thermal_zone_device *tz, unsigned long *temp)
bool wait;
u32 val;
+ mutex_lock(&data->mutex);
if (data->mode == THERMAL_DEVICE_ENABLED) {
/* Check if a measurement is currently in progress */
regmap_read(map, TEMPSENSE0, &val);
@@ -178,6 +180,7 @@ static int imx_get_temp(struct thermal_zone_device *tz, unsigned long *temp)
if ((val & TEMPSENSE0_FINISHED) == 0) {
dev_dbg(&tz->device, "temp measurement never finished\n");
+ mutex_unlock(&data->mutex);
return -EAGAIN;
}
@@ -205,6 +208,7 @@ static int imx_get_temp(struct thermal_zone_device *tz, unsigned long *temp)
data->irq_enabled = true;
enable_irq(data->irq);
}
+ mutex_unlock(&data->mutex);
return 0;
}
@@ -480,6 +484,8 @@ static int thermal_notifier_event(struct notifier_block *this,
{
struct regmap *map = imx_thermal_data->tempmon;
+ mutex_lock(&imx_thermal_data->mutex);
+
switch (event) {
/*
* In low_bus_freq_mode, the thermal sensor auto measurement
@@ -505,6 +511,8 @@ static int thermal_notifier_event(struct notifier_block *this,
default:
break;
}
+ mutex_unlock(&imx_thermal_data->mutex);
+
return NOTIFY_OK;
}
@@ -553,6 +561,7 @@ static int imx_thermal_probe(struct platform_device *pdev)
dev_warn(&pdev->dev, "failed to enable thermal clk: %d\n", ret);
}
+ mutex_init(&data->mutex);
/* make sure the IRQ flag is clear before enable irq */
regmap_write(map, MISC1 + REG_CLR, MISC1_IRQ_TEMPHIGH);
if (data->socdata->version == TEMPMON_V2) {