Loading Documentation/devicetree/bindings/thermal/imx-thermal.txt +4 −1 Original line number Diff line number Diff line * 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 Loading drivers/thermal/fair_share.c +12 −0 Original line number Diff line number Diff line Loading @@ -23,6 +23,7 @@ */ #include <linux/thermal.h> #include <trace/events/thermal.h> #include "thermal_core.h" Loading @@ -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; Loading @@ -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; } Loading drivers/thermal/imx_thermal.c +78 −13 Original line number Diff line number Diff line Loading @@ -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> Loading @@ -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 Loading @@ -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 Loading @@ -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; Loading @@ -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) { Loading Loading @@ -142,14 +182,18 @@ 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) /* 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) { 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) { dev_dbg(&tz->device, "millicelsius: %ld\n", *temp); Loading Loading @@ -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; Loading @@ -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; Loading Loading @@ -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); Loading Loading @@ -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", Loading drivers/thermal/of-thermal.c +12 −0 Original line number Diff line number Diff line Loading @@ -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", Loading Loading @@ -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", Loading Loading @@ -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; Loading drivers/thermal/step_wise.c +4 −1 Original line number Diff line number Diff line Loading @@ -23,6 +23,7 @@ */ #include <linux/thermal.h> #include <trace/events/thermal.h> #include "thermal_core.h" Loading Loading @@ -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); Loading Loading
Documentation/devicetree/bindings/thermal/imx-thermal.txt +4 −1 Original line number Diff line number Diff line * 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 Loading
drivers/thermal/fair_share.c +12 −0 Original line number Diff line number Diff line Loading @@ -23,6 +23,7 @@ */ #include <linux/thermal.h> #include <trace/events/thermal.h> #include "thermal_core.h" Loading @@ -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; Loading @@ -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; } Loading
drivers/thermal/imx_thermal.c +78 −13 Original line number Diff line number Diff line Loading @@ -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> Loading @@ -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 Loading @@ -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 Loading @@ -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; Loading @@ -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) { Loading Loading @@ -142,14 +182,18 @@ 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) /* 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) { 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) { dev_dbg(&tz->device, "millicelsius: %ld\n", *temp); Loading Loading @@ -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; Loading @@ -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; Loading Loading @@ -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); Loading Loading @@ -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", Loading
drivers/thermal/of-thermal.c +12 −0 Original line number Diff line number Diff line Loading @@ -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", Loading Loading @@ -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", Loading Loading @@ -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; Loading
drivers/thermal/step_wise.c +4 −1 Original line number Diff line number Diff line Loading @@ -23,6 +23,7 @@ */ #include <linux/thermal.h> #include <trace/events/thermal.h> #include "thermal_core.h" Loading Loading @@ -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); Loading