Skip to content

Commit

Permalink
Merge branch 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/…
Browse files Browse the repository at this point in the history
…evalenti/linux-soc-thermal into eduardo-soc
  • Loading branch information
Zhang Rui committed Aug 27, 2014
2 parents 52addcf + 3c94f17 commit 62ebb7b
Show file tree
Hide file tree
Showing 7 changed files with 200 additions and 15 deletions.
5 changes: 4 additions & 1 deletion Documentation/devicetree/bindings/thermal/imx-thermal.txt
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
* Temperature Monitor (TEMPMON) on Freescale i.MX SoCs

Required properties:
- compatible : "fsl,imx6q-thermal"
- compatible : "fsl,imx6q-tempmon" for i.MX6Q, "fsl,imx6sx-tempmon" for i.MX6SX.
i.MX6SX has two more IRQs than i.MX6Q, one is IRQ_LOW and the other is IRQ_PANIC,
when temperature is below than low threshold, IRQ_LOW will be triggered, when temperature
is higher than panic threshold, system will auto reboot by SRC module.
- fsl,tempmon : phandle pointer to system controller that contains TEMPMON
control registers, e.g. ANATOP on imx6q.
- fsl,tempmon-data : phandle pointer to fuse controller that contains TEMPMON
Expand Down
12 changes: 12 additions & 0 deletions drivers/thermal/fair_share.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
*/

#include <linux/thermal.h>
#include <trace/events/thermal.h>

#include "thermal_core.h"

Expand All @@ -34,6 +35,7 @@ static int get_trip_level(struct thermal_zone_device *tz)
{
int count = 0;
unsigned long trip_temp;
enum thermal_trip_type trip_type;

if (tz->trips == 0 || !tz->ops->get_trip_temp)
return 0;
Expand All @@ -43,6 +45,16 @@ static int get_trip_level(struct thermal_zone_device *tz)
if (tz->temperature < trip_temp)
break;
}

/*
* count > 0 only if temperature is greater than first trip
* point, in which case, trip_point = count - 1
*/
if (count > 0) {
tz->ops->get_trip_type(tz, count - 1, &trip_type);
trace_thermal_zone_trip(tz, count - 1, trip_type);
}

return count;
}

Expand Down
91 changes: 78 additions & 13 deletions drivers/thermal/imx_thermal.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
#include <linux/mfd/syscon.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/platform_device.h>
#include <linux/regmap.h>
#include <linux/slab.h>
Expand All @@ -31,6 +32,11 @@

#define MISC0 0x0150
#define MISC0_REFTOP_SELBIASOFF (1 << 3)
#define MISC1 0x0160
#define MISC1_IRQ_TEMPHIGH (1 << 29)
/* Below LOW and PANIC bits are only for TEMPMON_IMX6SX */
#define MISC1_IRQ_TEMPLOW (1 << 28)
#define MISC1_IRQ_TEMPPANIC (1 << 27)

#define TEMPSENSE0 0x0180
#define TEMPSENSE0_ALARM_VALUE_SHIFT 20
Expand All @@ -43,6 +49,12 @@

#define TEMPSENSE1 0x0190
#define TEMPSENSE1_MEASURE_FREQ 0xffff
/* Below TEMPSENSE2 is only for TEMPMON_IMX6SX */
#define TEMPSENSE2 0x0290
#define TEMPSENSE2_LOW_VALUE_SHIFT 0
#define TEMPSENSE2_LOW_VALUE_MASK 0xfff
#define TEMPSENSE2_PANIC_VALUE_SHIFT 16
#define TEMPSENSE2_PANIC_VALUE_MASK 0xfff0000

#define OCOTP_ANA1 0x04e0

Expand All @@ -66,6 +78,21 @@ enum imx_thermal_trip {
#define FACTOR1 15976
#define FACTOR2 4297157

#define TEMPMON_IMX6Q 1
#define TEMPMON_IMX6SX 2

struct thermal_soc_data {
u32 version;
};

static struct thermal_soc_data thermal_imx6q_data = {
.version = TEMPMON_IMX6Q,
};

static struct thermal_soc_data thermal_imx6sx_data = {
.version = TEMPMON_IMX6SX,
};

struct imx_thermal_data {
struct thermal_zone_device *tz;
struct thermal_cooling_device *cdev;
Expand All @@ -79,8 +106,21 @@ struct imx_thermal_data {
bool irq_enabled;
int irq;
struct clk *thermal_clk;
const struct thermal_soc_data *socdata;
};

static void imx_set_panic_temp(struct imx_thermal_data *data,
signed long panic_temp)
{
struct regmap *map = data->tempmon;
int critical_value;

critical_value = (data->c2 - panic_temp) / data->c1;
regmap_write(map, TEMPSENSE2 + REG_CLR, TEMPSENSE2_PANIC_VALUE_MASK);
regmap_write(map, TEMPSENSE2 + REG_SET, critical_value <<
TEMPSENSE2_PANIC_VALUE_SHIFT);
}

static void imx_set_alarm_temp(struct imx_thermal_data *data,
signed long alarm_temp)
{
Expand Down Expand Up @@ -142,13 +182,17 @@ static int imx_get_temp(struct thermal_zone_device *tz, unsigned long *temp)
/* See imx_get_sensor_data() for formula derivation */
*temp = data->c2 - n_meas * data->c1;

/* Update alarm value to next higher trip point */
if (data->alarm_temp == data->temp_passive && *temp >= data->temp_passive)
imx_set_alarm_temp(data, data->temp_critical);
if (data->alarm_temp == data->temp_critical && *temp < data->temp_passive) {
imx_set_alarm_temp(data, data->temp_passive);
dev_dbg(&tz->device, "thermal alarm off: T < %lu\n",
data->alarm_temp / 1000);
/* Update alarm value to next higher trip point for TEMPMON_IMX6Q */
if (data->socdata->version == TEMPMON_IMX6Q) {
if (data->alarm_temp == data->temp_passive &&
*temp >= data->temp_passive)
imx_set_alarm_temp(data, data->temp_critical);
if (data->alarm_temp == data->temp_critical &&
*temp < data->temp_passive) {
imx_set_alarm_temp(data, data->temp_passive);
dev_dbg(&tz->device, "thermal alarm off: T < %lu\n",
data->alarm_temp / 1000);
}
}

if (*temp != data->last_temp) {
Expand Down Expand Up @@ -398,8 +442,17 @@ static irqreturn_t imx_thermal_alarm_irq_thread(int irq, void *dev)
return IRQ_HANDLED;
}

static const struct of_device_id of_imx_thermal_match[] = {
{ .compatible = "fsl,imx6q-tempmon", .data = &thermal_imx6q_data, },
{ .compatible = "fsl,imx6sx-tempmon", .data = &thermal_imx6sx_data, },
{ /* end */ }
};
MODULE_DEVICE_TABLE(of, of_imx_thermal_match);

static int imx_thermal_probe(struct platform_device *pdev)
{
const struct of_device_id *of_id =
of_match_device(of_imx_thermal_match, &pdev->dev);
struct imx_thermal_data *data;
struct cpumask clip_cpus;
struct regmap *map;
Expand All @@ -418,6 +471,20 @@ static int imx_thermal_probe(struct platform_device *pdev)
}
data->tempmon = map;

data->socdata = of_id->data;

/* make sure the IRQ flag is clear before enabling irq on i.MX6SX */
if (data->socdata->version == TEMPMON_IMX6SX) {
regmap_write(map, MISC1 + REG_CLR, MISC1_IRQ_TEMPHIGH |
MISC1_IRQ_TEMPLOW | MISC1_IRQ_TEMPPANIC);
/*
* reset value of LOW ALARM is incorrect, set it to lowest
* value to avoid false trigger of low alarm.
*/
regmap_write(map, TEMPSENSE2 + REG_SET,
TEMPSENSE2_LOW_VALUE_MASK);
}

data->irq = platform_get_irq(pdev, 0);
if (data->irq < 0)
return data->irq;
Expand Down Expand Up @@ -489,6 +556,10 @@ static int imx_thermal_probe(struct platform_device *pdev)
measure_freq = DIV_ROUND_UP(32768, 10); /* 10 Hz */
regmap_write(map, TEMPSENSE1 + REG_SET, measure_freq);
imx_set_alarm_temp(data, data->temp_passive);

if (data->socdata->version == TEMPMON_IMX6SX)
imx_set_panic_temp(data, data->temp_critical);

regmap_write(map, TEMPSENSE0 + REG_CLR, TEMPSENSE0_POWER_DOWN);
regmap_write(map, TEMPSENSE0 + REG_SET, TEMPSENSE0_MEASURE_TEMP);

Expand Down Expand Up @@ -550,12 +621,6 @@ static int imx_thermal_resume(struct device *dev)
static SIMPLE_DEV_PM_OPS(imx_thermal_pm_ops,
imx_thermal_suspend, imx_thermal_resume);

static const struct of_device_id of_imx_thermal_match[] = {
{ .compatible = "fsl,imx6q-tempmon", },
{ /* end */ }
};
MODULE_DEVICE_TABLE(of, of_imx_thermal_match);

static struct platform_driver imx_thermal = {
.driver = {
.name = "imx_thermal",
Expand Down
12 changes: 12 additions & 0 deletions drivers/thermal/of-thermal.c
Original file line number Diff line number Diff line change
Expand Up @@ -401,6 +401,10 @@ thermal_zone_of_sensor_register(struct device *dev, int sensor_id,
struct of_phandle_args sensor_specs;
int ret, id;

/* Check whether child is enabled or not */
if (!of_device_is_available(child))
continue;

/* For now, thermal framework supports only 1 sensor per zone */
ret = of_parse_phandle_with_args(child, "thermal-sensors",
"#thermal-sensor-cells",
Expand Down Expand Up @@ -771,6 +775,10 @@ int __init of_parse_thermal_zones(void)
struct thermal_zone_device *zone;
struct thermal_zone_params *tzp;

/* Check whether child is enabled or not */
if (!of_device_is_available(child))
continue;

tz = thermal_of_build_thermal_zone(child);
if (IS_ERR(tz)) {
pr_err("failed to build thermal zone %s: %ld\n",
Expand Down Expand Up @@ -838,6 +846,10 @@ void of_thermal_destroy_zones(void)
for_each_child_of_node(np, child) {
struct thermal_zone_device *zone;

/* Check whether child is enabled or not */
if (!of_device_is_available(child))
continue;

zone = thermal_zone_get_zone_by_name(child->name);
if (IS_ERR(zone))
continue;
Expand Down
5 changes: 4 additions & 1 deletion drivers/thermal/step_wise.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
*/

#include <linux/thermal.h>
#include <trace/events/thermal.h>

#include "thermal_core.h"

Expand Down Expand Up @@ -129,8 +130,10 @@ static void thermal_zone_trip_update(struct thermal_zone_device *tz, int trip)

trend = get_tz_trend(tz, trip);

if (tz->temperature >= trip_temp)
if (tz->temperature >= trip_temp) {
throttle = true;
trace_thermal_zone_trip(tz, trip, trip_type);
}

dev_dbg(&tz->device, "Trip%d[type=%d,temp=%ld]:trend=%d,throttle=%d\n",
trip, trip_type, trip_temp, trend, throttle);
Expand Down
7 changes: 7 additions & 0 deletions drivers/thermal/thermal_core.c
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,9 @@
#include <net/netlink.h>
#include <net/genetlink.h>

#define CREATE_TRACE_POINTS
#include <trace/events/thermal.h>

#include "thermal_core.h"
#include "thermal_hwmon.h"

Expand Down Expand Up @@ -368,6 +371,8 @@ static void handle_critical_trips(struct thermal_zone_device *tz,
if (tz->temperature < trip_temp)
return;

trace_thermal_zone_trip(tz, trip, trip_type);

if (tz->ops->notify)
tz->ops->notify(tz, trip, trip_type);

Expand Down Expand Up @@ -463,6 +468,7 @@ static void update_temperature(struct thermal_zone_device *tz)
tz->temperature = temp;
mutex_unlock(&tz->lock);

trace_thermal_temperature(tz);
dev_dbg(&tz->device, "last_temperature=%d, current_temperature=%d\n",
tz->last_temperature, tz->temperature);
}
Expand Down Expand Up @@ -1287,6 +1293,7 @@ void thermal_cdev_update(struct thermal_cooling_device *cdev)
mutex_unlock(&cdev->lock);
cdev->ops->set_cur_state(cdev, target);
cdev->updated = true;
trace_cdev_update(cdev, target);
dev_dbg(&cdev->device, "set to state %lu\n", target);
}
EXPORT_SYMBOL(thermal_cdev_update);
Expand Down
83 changes: 83 additions & 0 deletions include/trace/events/thermal.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
#undef TRACE_SYSTEM
#define TRACE_SYSTEM thermal

#if !defined(_TRACE_THERMAL_H) || defined(TRACE_HEADER_MULTI_READ)
#define _TRACE_THERMAL_H

#include <linux/thermal.h>
#include <linux/tracepoint.h>

TRACE_EVENT(thermal_temperature,

TP_PROTO(struct thermal_zone_device *tz),

TP_ARGS(tz),

TP_STRUCT__entry(
__string(thermal_zone, tz->type)
__field(int, id)
__field(int, temp_prev)
__field(int, temp)
),

TP_fast_assign(
__assign_str(thermal_zone, tz->type);
__entry->id = tz->id;
__entry->temp_prev = tz->last_temperature;
__entry->temp = tz->temperature;
),

TP_printk("thermal_zone=%s id=%d temp_prev=%d temp=%d",
__get_str(thermal_zone), __entry->id, __entry->temp_prev,
__entry->temp)
);

TRACE_EVENT(cdev_update,

TP_PROTO(struct thermal_cooling_device *cdev, unsigned long target),

TP_ARGS(cdev, target),

TP_STRUCT__entry(
__string(type, cdev->type)
__field(unsigned long, target)
),

TP_fast_assign(
__assign_str(type, cdev->type);
__entry->target = target;
),

TP_printk("type=%s target=%lu", __get_str(type), __entry->target)
);

TRACE_EVENT(thermal_zone_trip,

TP_PROTO(struct thermal_zone_device *tz, int trip,
enum thermal_trip_type trip_type),

TP_ARGS(tz, trip, trip_type),

TP_STRUCT__entry(
__string(thermal_zone, tz->type)
__field(int, id)
__field(int, trip)
__field(enum thermal_trip_type, trip_type)
),

TP_fast_assign(
__assign_str(thermal_zone, tz->type);
__entry->id = tz->id;
__entry->trip = trip;
__entry->trip_type = trip_type;
),

TP_printk("thermal_zone=%s id=%d trip=%d trip_type=%d",
__get_str(thermal_zone), __entry->id, __entry->trip,
__entry->trip_type)
);

#endif /* _TRACE_THERMAL_H */

/* This part must be outside protection */
#include <trace/define_trace.h>

0 comments on commit 62ebb7b

Please sign in to comment.