From bb431ba26c5cd0a17c941ca6c3a195a3a6d5d461 Mon Sep 17 00:00:00 2001 From: Zhang Rui Date: Fri, 30 Oct 2015 16:31:47 +0800 Subject: [PATCH 01/14] Thermal: initialize thermal zone device correctly After thermal zone device registered, as we have not read any temperature before, thus tz->temperature should not be 0, which actually means 0C, and thermal trend is not available. In this case, we need specially handling for the first thermal_zone_device_update(). Both thermal core framework and step_wise governor is enhanced to handle this. And since the step_wise governor is the only one that uses trends, so it's the only thermal governor that needs to be updated. CC: #3.18+ Tested-by: Manuel Krause Tested-by: szegad Tested-by: prash Tested-by: amish Tested-by: Matthias Reviewed-by: Javi Merino Signed-off-by: Zhang Rui Signed-off-by: Chen Yu --- drivers/thermal/step_wise.c | 17 +++++++++++++++-- drivers/thermal/thermal_core.c | 19 +++++++++++++++++-- drivers/thermal/thermal_core.h | 1 + include/linux/thermal.h | 3 +++ 4 files changed, 36 insertions(+), 4 deletions(-) diff --git a/drivers/thermal/step_wise.c b/drivers/thermal/step_wise.c index 2f9f7086ac3d..ea9366ad3e6b 100644 --- a/drivers/thermal/step_wise.c +++ b/drivers/thermal/step_wise.c @@ -63,6 +63,19 @@ static unsigned long get_target_state(struct thermal_instance *instance, next_target = instance->target; dev_dbg(&cdev->device, "cur_state=%ld\n", cur_state); + if (!instance->initialized) { + if (throttle) { + next_target = (cur_state + 1) >= instance->upper ? + instance->upper : + ((cur_state + 1) < instance->lower ? + instance->lower : (cur_state + 1)); + } else { + next_target = THERMAL_NO_TARGET; + } + + return next_target; + } + switch (trend) { case THERMAL_TREND_RAISING: if (throttle) { @@ -149,7 +162,7 @@ static void thermal_zone_trip_update(struct thermal_zone_device *tz, int trip) dev_dbg(&instance->cdev->device, "old_target=%d, target=%d\n", old_target, (int)instance->target); - if (old_target == instance->target) + if (instance->initialized && old_target == instance->target) continue; /* Activate a passive thermal instance */ @@ -161,7 +174,7 @@ static void thermal_zone_trip_update(struct thermal_zone_device *tz, int trip) instance->target == THERMAL_NO_TARGET) update_passive_instance(tz, trip_type, -1); - + instance->initialized = true; instance->cdev->updated = false; /* cdev needs update */ } diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c index d9e525cc9c1c..682bc1ef9c37 100644 --- a/drivers/thermal/thermal_core.c +++ b/drivers/thermal/thermal_core.c @@ -532,8 +532,22 @@ static void update_temperature(struct thermal_zone_device *tz) mutex_unlock(&tz->lock); trace_thermal_temperature(tz); - dev_dbg(&tz->device, "last_temperature=%d, current_temperature=%d\n", - tz->last_temperature, tz->temperature); + if (tz->last_temperature == THERMAL_TEMP_INVALID) + dev_dbg(&tz->device, "last_temperature N/A, current_temperature=%d\n", + tz->temperature); + else + dev_dbg(&tz->device, "last_temperature=%d, current_temperature=%d\n", + tz->last_temperature, tz->temperature); +} + +static void thermal_zone_device_reset(struct thermal_zone_device *tz) +{ + struct thermal_instance *pos; + + tz->temperature = THERMAL_TEMP_INVALID; + tz->passive = 0; + list_for_each_entry(pos, &tz->thermal_instances, tz_node) + pos->initialized = false; } void thermal_zone_device_update(struct thermal_zone_device *tz) @@ -1900,6 +1914,7 @@ struct thermal_zone_device *thermal_zone_device_register(const char *type, INIT_DELAYED_WORK(&(tz->poll_queue), thermal_zone_device_check); + thermal_zone_device_reset(tz); thermal_zone_device_update(tz); return tz; diff --git a/drivers/thermal/thermal_core.h b/drivers/thermal/thermal_core.h index d7ac1fccd659..749d41abfbab 100644 --- a/drivers/thermal/thermal_core.h +++ b/drivers/thermal/thermal_core.h @@ -41,6 +41,7 @@ struct thermal_instance { struct thermal_zone_device *tz; struct thermal_cooling_device *cdev; int trip; + bool initialized; unsigned long upper; /* Highest cooling state for this trip point */ unsigned long lower; /* Lowest cooling state for this trip point */ unsigned long target; /* expected cooling state */ diff --git a/include/linux/thermal.h b/include/linux/thermal.h index 613c29bd6baf..103fcbe6bdaf 100644 --- a/include/linux/thermal.h +++ b/include/linux/thermal.h @@ -43,6 +43,9 @@ /* Default weight of a bound cooling device */ #define THERMAL_WEIGHT_DEFAULT 0 +/* use value, which < 0K, to indicate an invalid/uninitialized temperature */ +#define THERMAL_TEMP_INVALID -274000 + /* Unit conversion macros */ #define DECI_KELVIN_TO_CELSIUS(t) ({ \ long _t = (t); \ From ff140fea847e1c2002a220571ab106c2456ed252 Mon Sep 17 00:00:00 2001 From: Zhang Rui Date: Fri, 30 Oct 2015 16:31:58 +0800 Subject: [PATCH 02/14] Thermal: handle thermal zone device properly during system sleep Current thermal code does not handle system sleep well because 1. the cooling device cooling state may be changed during suspend 2. the previous temperature reading becomes invalid after resumed because it is got before system sleep 3. updating thermal zone device during suspending/resuming is wrong because some devices may have already been suspended or may have not been resumed. Thus, the proper way to do this is to cancel all thermal zone device update requirements during suspend/resume, and after all the devices have been resumed, reset and update every registered thermal zone devices. This also fixes a regression introduced by: Commit 19593a1fb1f6 ("ACPI / fan: convert to platform driver") Because, with above commit applied, all the fan devices are attached to the acpi_general_pm_domain, and they are turned on by the pm_domain automatically after resume, without the awareness of thermal core. CC: #3.18+ Reference: https://bugzilla.kernel.org/show_bug.cgi?id=78201 Reference: https://bugzilla.kernel.org/show_bug.cgi?id=91411 Tested-by: Manuel Krause Tested-by: szegad Tested-by: prash Tested-by: amish Tested-by: Matthias Reviewed-by: Javi Merino Signed-off-by: Zhang Rui Signed-off-by: Chen Yu --- drivers/thermal/thermal_core.c | 42 ++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c index 682bc1ef9c37..9aae767bf39b 100644 --- a/drivers/thermal/thermal_core.c +++ b/drivers/thermal/thermal_core.c @@ -37,6 +37,7 @@ #include #include #include +#include #define CREATE_TRACE_POINTS #include @@ -59,6 +60,8 @@ static LIST_HEAD(thermal_governor_list); static DEFINE_MUTEX(thermal_list_lock); static DEFINE_MUTEX(thermal_governor_lock); +static atomic_t in_suspend; + static struct thermal_governor *def_governor; static struct thermal_governor *__find_governor(const char *name) @@ -554,6 +557,9 @@ void thermal_zone_device_update(struct thermal_zone_device *tz) { int count; + if (atomic_read(&in_suspend)) + return; + if (!tz->ops->get_temp) return; @@ -2155,6 +2161,36 @@ static void thermal_unregister_governors(void) thermal_gov_power_allocator_unregister(); } +static int thermal_pm_notify(struct notifier_block *nb, + unsigned long mode, void *_unused) +{ + struct thermal_zone_device *tz; + + switch (mode) { + case PM_HIBERNATION_PREPARE: + case PM_RESTORE_PREPARE: + case PM_SUSPEND_PREPARE: + atomic_set(&in_suspend, 1); + break; + case PM_POST_HIBERNATION: + case PM_POST_RESTORE: + case PM_POST_SUSPEND: + atomic_set(&in_suspend, 0); + list_for_each_entry(tz, &thermal_tz_list, node) { + thermal_zone_device_reset(tz); + thermal_zone_device_update(tz); + } + break; + default: + break; + } + return 0; +} + +static struct notifier_block thermal_pm_nb = { + .notifier_call = thermal_pm_notify, +}; + static int __init thermal_init(void) { int result; @@ -2175,6 +2211,11 @@ static int __init thermal_init(void) if (result) goto exit_netlink; + result = register_pm_notifier(&thermal_pm_nb); + if (result) + pr_warn("Thermal: Can not register suspend notifier, return %d\n", + result); + return 0; exit_netlink: @@ -2194,6 +2235,7 @@ error: static void __exit thermal_exit(void) { + unregister_pm_notifier(&thermal_pm_nb); of_thermal_destroy_zones(); genetlink_exit(); class_unregister(&thermal_class); From 4511f7166a2deb5f7a578cf87fd2fe1ae83527e3 Mon Sep 17 00:00:00 2001 From: Chen Yu Date: Fri, 30 Oct 2015 16:32:10 +0800 Subject: [PATCH 03/14] Thermal: do thermal zone update after a cooling device registered When a new cooling device is registered, we need to update the thermal zone to set the new registered cooling device to a proper state. This fixes a problem that the system is cool, while the fan devices are left running on full speed after boot, if fan device is registered after thermal zone device. Here is the history of why current patch looks like this: https://patchwork.kernel.org/patch/7273041/ CC: #3.18+ Reference:https://bugzilla.kernel.org/show_bug.cgi?id=92431 Tested-by: Manuel Krause Tested-by: szegad Tested-by: prash Tested-by: amish Reviewed-by: Javi Merino Signed-off-by: Zhang Rui Signed-off-by: Chen Yu --- drivers/thermal/thermal_core.c | 14 +++++++++++++- include/linux/thermal.h | 2 ++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c index 9aae767bf39b..ba08b5521382 100644 --- a/drivers/thermal/thermal_core.c +++ b/drivers/thermal/thermal_core.c @@ -1341,6 +1341,7 @@ int thermal_zone_bind_cooling_device(struct thermal_zone_device *tz, if (!result) { list_add_tail(&dev->tz_node, &tz->thermal_instances); list_add_tail(&dev->cdev_node, &cdev->thermal_instances); + atomic_set(&tz->need_update, 1); } mutex_unlock(&cdev->lock); mutex_unlock(&tz->lock); @@ -1450,6 +1451,7 @@ __thermal_cooling_device_register(struct device_node *np, const struct thermal_cooling_device_ops *ops) { struct thermal_cooling_device *cdev; + struct thermal_zone_device *pos = NULL; int result; if (type && strlen(type) >= THERMAL_NAME_LENGTH) @@ -1494,6 +1496,12 @@ __thermal_cooling_device_register(struct device_node *np, /* Update binding information for 'this' new cdev */ bind_cdev(cdev); + mutex_lock(&thermal_list_lock); + list_for_each_entry(pos, &thermal_tz_list, node) + if (atomic_cmpxchg(&pos->need_update, 1, 0)) + thermal_zone_device_update(pos); + mutex_unlock(&thermal_list_lock); + return cdev; } @@ -1826,6 +1834,8 @@ struct thermal_zone_device *thermal_zone_device_register(const char *type, tz->trips = trips; tz->passive_delay = passive_delay; tz->polling_delay = polling_delay; + /* A new thermal zone needs to be updated anyway. */ + atomic_set(&tz->need_update, 1); dev_set_name(&tz->device, "thermal_zone%d", tz->id); result = device_register(&tz->device); @@ -1921,7 +1931,9 @@ struct thermal_zone_device *thermal_zone_device_register(const char *type, INIT_DELAYED_WORK(&(tz->poll_queue), thermal_zone_device_check); thermal_zone_device_reset(tz); - thermal_zone_device_update(tz); + /* Update the new thermal zone and mark it as already updated. */ + if (atomic_cmpxchg(&tz->need_update, 1, 0)) + thermal_zone_device_update(tz); return tz; diff --git a/include/linux/thermal.h b/include/linux/thermal.h index 103fcbe6bdaf..e13a1ace50e9 100644 --- a/include/linux/thermal.h +++ b/include/linux/thermal.h @@ -170,6 +170,7 @@ struct thermal_attr { * @forced_passive: If > 0, temperature at which to switch on all ACPI * processor cooling devices. Currently only used by the * step-wise governor. + * @need_update: if equals 1, thermal_zone_device_update needs to be invoked. * @ops: operations this &thermal_zone_device supports * @tzp: thermal zone parameters * @governor: pointer to the governor for this thermal zone @@ -197,6 +198,7 @@ struct thermal_zone_device { int emul_temperature; int passive; unsigned int forced_passive; + atomic_t need_update; struct thermal_zone_device_ops *ops; struct thermal_zone_params *tzp; struct thermal_governor *governor; From a96bedf1b8e50c46d3b486294a8972c90aadc0cb Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Sun, 11 Oct 2015 13:01:28 +0200 Subject: [PATCH 04/14] thermal: constify pch_dev_ops structure The pch_dev_ops structure is never modified. It is only stored in a field that is already declared as const. Done with the help of Coccinelle. Signed-off-by: Julia Lawall Signed-off-by: Zhang Rui --- drivers/thermal/intel_pch_thermal.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/thermal/intel_pch_thermal.c b/drivers/thermal/intel_pch_thermal.c index 50c7da79be83..00d81af648b8 100644 --- a/drivers/thermal/intel_pch_thermal.c +++ b/drivers/thermal/intel_pch_thermal.c @@ -136,7 +136,7 @@ struct pch_dev_ops { /* dev ops for Wildcat Point */ -static struct pch_dev_ops pch_dev_ops_wpt = { +static const struct pch_dev_ops pch_dev_ops_wpt = { .hw_init = pch_wpt_init, .get_temp = pch_wpt_get_temp, }; From 20bbfaf72cb419cf2a864978df3fc36f1986046a Mon Sep 17 00:00:00 2001 From: Amy Wiles Date: Wed, 14 Oct 2015 08:09:14 -0700 Subject: [PATCH 05/14] Thermal: Enable Broxton SoC thermal reporting device Signed-off-by: Amy Wiles Signed-off-by: Zhang Rui --- .../thermal/int340x_thermal/processor_thermal_device.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/drivers/thermal/int340x_thermal/processor_thermal_device.c b/drivers/thermal/int340x_thermal/processor_thermal_device.c index ccc0ad02d066..36fa724a36c8 100644 --- a/drivers/thermal/int340x_thermal/processor_thermal_device.c +++ b/drivers/thermal/int340x_thermal/processor_thermal_device.c @@ -33,6 +33,12 @@ /* Braswell thermal reporting device */ #define PCI_DEVICE_ID_PROC_BSW_THERMAL 0x22DC +/* Broxton thermal reporting device */ +#define PCI_DEVICE_ID_PROC_BXT0_THERMAL 0x0A8C +#define PCI_DEVICE_ID_PROC_BXT1_THERMAL 0x1A8C +#define PCI_DEVICE_ID_PROC_BXTX_THERMAL 0x4A8C +#define PCI_DEVICE_ID_PROC_BXTP_THERMAL 0x5A8C + struct power_config { u32 index; u32 min_uw; @@ -404,6 +410,10 @@ static const struct pci_device_id proc_thermal_pci_ids[] = { { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_PROC_HSB_THERMAL)}, { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_PROC_SKL_THERMAL)}, { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_PROC_BSW_THERMAL)}, + { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_PROC_BXT0_THERMAL)}, + { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_PROC_BXT1_THERMAL)}, + { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_PROC_BXTX_THERMAL)}, + { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_PROC_BXTP_THERMAL)}, { 0, }, }; From 13c1cfda1a6cb0325029ce8bbb8d6483244d5c92 Mon Sep 17 00:00:00 2001 From: Caesar Wang Date: Thu, 3 Dec 2015 16:48:39 +0800 Subject: [PATCH 06/14] thermal: rockchip: fix a trivial typo This patchset trys to dictate unified format for driver. Signed-off-by: Caesar Wang Signed-off-by: Eduardo Valentin --- drivers/thermal/rockchip_thermal.c | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/drivers/thermal/rockchip_thermal.c b/drivers/thermal/rockchip_thermal.c index e845841ab036..ae796eca2ff5 100644 --- a/drivers/thermal/rockchip_thermal.c +++ b/drivers/thermal/rockchip_thermal.c @@ -38,7 +38,7 @@ enum tshut_mode { }; /** - * the system Temperature Sensors tshut(tshut) polarity + * The system Temperature Sensors tshut(tshut) polarity * the bit 8 is tshut polarity. * 0: low active, 1: high active */ @@ -57,10 +57,10 @@ enum sensor_id { }; /** -* The conversion table has the adc value and temperature. -* ADC_DECREMENT is the adc value decremnet.(e.g. v2_code_table) -* ADC_INCREMNET is the adc value incremnet.(e.g. v3_code_table) -*/ + * The conversion table has the adc value and temperature. + * ADC_DECREMENT: the adc value is of diminishing.(e.g. v2_code_table) + * ADC_INCREMENT: the adc value is incremental.(e.g. v3_code_table) + */ enum adc_sort_mode { ADC_DECREMENT = 0, ADC_INCREMENT, @@ -72,16 +72,17 @@ enum adc_sort_mode { */ #define SOC_MAX_SENSORS 2 +/** + * struct chip_tsadc_table: hold information about chip-specific differences + * @id: conversion table + * @length: size of conversion table + * @data_mask: mask to apply on data inputs + * @mode: sort mode of this adc variant (incrementing or decrementing) + */ struct chip_tsadc_table { const struct tsadc_table *id; - - /* the array table size*/ unsigned int length; - - /* that analogic mask data */ u32 data_mask; - - /* the sort mode is adc value that increment or decrement in table */ enum adc_sort_mode mode; }; @@ -617,7 +618,7 @@ rockchip_thermal_register_sensor(struct platform_device *pdev, return 0; } -/* +/** * Reset TSADC Controller, reset all tsadc registers. */ static void rockchip_thermal_reset_controller(struct reset_control *reset) From 4be02530fc76b4b01372dc03ab098674bf059f0b Mon Sep 17 00:00:00 2001 From: Caesar Wang Date: Thu, 3 Dec 2015 16:48:41 +0800 Subject: [PATCH 07/14] dt-bindings: rockchip-thermal: Support the RK3228/RK3399 SoCs compatible This patchset attempts to new compatible for thermal founding on RK3228/RK3399 SoCs. Signed-off-by: Caesar Wang Acked-by: Rob Herring Signed-off-by: Eduardo Valentin --- Documentation/devicetree/bindings/thermal/rockchip-thermal.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Documentation/devicetree/bindings/thermal/rockchip-thermal.txt b/Documentation/devicetree/bindings/thermal/rockchip-thermal.txt index 0dfa60d88dd3..08efe6bc2193 100644 --- a/Documentation/devicetree/bindings/thermal/rockchip-thermal.txt +++ b/Documentation/devicetree/bindings/thermal/rockchip-thermal.txt @@ -2,8 +2,10 @@ Required properties: - compatible : should be "rockchip,-tsadc" + "rockchip,rk3228-tsadc": found on RK3228 SoCs "rockchip,rk3288-tsadc": found on RK3288 SoCs "rockchip,rk3368-tsadc": found on RK3368 SoCs + "rockchip,rk3399-tsadc": found on RK3399 SoCs - reg : physical base address of the controller and length of memory mapped region. - interrupts : The interrupt number to the cpu. The interrupt specifier format From 7b02a5e782fa151a610c455ac06e5a998e9cb3f3 Mon Sep 17 00:00:00 2001 From: Caesar Wang Date: Thu, 3 Dec 2015 16:48:42 +0800 Subject: [PATCH 08/14] thermal: rockchip: Support the RK3228 SoCs in thermal driver The RK3228 SoCs has one Temperature Sensor, channel 0 is for CPU. Signed-off-by: Caesar Wang Signed-off-by: Eduardo Valentin --- drivers/thermal/rockchip_thermal.c | 81 ++++++++++++++++++++++++++++++ 1 file changed, 81 insertions(+) diff --git a/drivers/thermal/rockchip_thermal.c b/drivers/thermal/rockchip_thermal.c index ae796eca2ff5..e118e42c0326 100644 --- a/drivers/thermal/rockchip_thermal.c +++ b/drivers/thermal/rockchip_thermal.c @@ -154,6 +154,7 @@ struct rockchip_thermal_data { #define TSADCV2_SHUT_2GPIO_SRC_EN(chn) BIT(4 + (chn)) #define TSADCV2_SHUT_2CRU_SRC_EN(chn) BIT(8 + (chn)) +#define TSADCV1_INT_PD_CLEAR_MASK ~BIT(16) #define TSADCV2_INT_PD_CLEAR_MASK ~BIT(8) #define TSADCV2_DATA_MASK 0xfff @@ -169,6 +170,51 @@ struct tsadc_table { int temp; }; +/** + * Note: + * Code to Temperature mapping of the Temperature sensor is a piece wise linear + * curve.Any temperature, code faling between to 2 give temperatures can be + * linearly interpolated. + * Code to Temperature mapping should be updated based on sillcon results. + */ +static const struct tsadc_table v1_code_table[] = { + {TSADCV3_DATA_MASK, -40000}, + {436, -40000}, + {431, -35000}, + {426, -30000}, + {421, -25000}, + {416, -20000}, + {411, -15000}, + {406, -10000}, + {401, -5000}, + {395, 0}, + {390, 5000}, + {385, 10000}, + {380, 15000}, + {375, 20000}, + {370, 25000}, + {364, 30000}, + {359, 35000}, + {354, 40000}, + {349, 45000}, + {343, 50000}, + {338, 55000}, + {333, 60000}, + {328, 65000}, + {322, 70000}, + {317, 75000}, + {312, 80000}, + {307, 85000}, + {301, 90000}, + {296, 95000}, + {291, 100000}, + {286, 105000}, + {280, 110000}, + {275, 115000}, + {270, 120000}, + {264, 125000}, +}; + static const struct tsadc_table v2_code_table[] = { {TSADCV2_DATA_MASK, -40000}, {3800, -40000}, @@ -369,6 +415,14 @@ static void rk_tsadcv2_initialize(void __iomem *regs, regs + TSADCV2_HIGHT_TSHUT_DEBOUNCE); } +static void rk_tsadcv1_irq_ack(void __iomem *regs) +{ + u32 val; + + val = readl_relaxed(regs + TSADCV2_INT_PD); + writel_relaxed(val & TSADCV1_INT_PD_CLEAR_MASK, regs + TSADCV2_INT_PD); +} + static void rk_tsadcv2_irq_ack(void __iomem *regs) { u32 val; @@ -430,6 +484,29 @@ static void rk_tsadcv2_tshut_mode(int chn, void __iomem *regs, writel_relaxed(val, regs + TSADCV2_INT_EN); } +static const struct rockchip_tsadc_chip rk3228_tsadc_data = { + .chn_id[SENSOR_CPU] = 0, /* cpu sensor is channel 0 */ + .chn_num = 1, /* one channel for tsadc */ + + .tshut_mode = TSHUT_MODE_GPIO, /* default TSHUT via GPIO give PMIC */ + .tshut_polarity = TSHUT_LOW_ACTIVE, /* default TSHUT LOW ACTIVE */ + .tshut_temp = 95000, + + .initialize = rk_tsadcv2_initialize, + .irq_ack = rk_tsadcv1_irq_ack, + .control = rk_tsadcv2_control, + .get_temp = rk_tsadcv2_get_temp, + .set_tshut_temp = rk_tsadcv2_tshut_temp, + .set_tshut_mode = rk_tsadcv2_tshut_mode, + + .table = { + .id = v1_code_table, + .length = ARRAY_SIZE(v1_code_table), + .data_mask = TSADCV3_DATA_MASK, + .mode = ADC_DECREMENT, + }, +}; + static const struct rockchip_tsadc_chip rk3288_tsadc_data = { .chn_id[SENSOR_CPU] = 1, /* cpu sensor is channel 1 */ .chn_id[SENSOR_GPU] = 2, /* gpu sensor is channel 2 */ @@ -479,6 +556,10 @@ static const struct rockchip_tsadc_chip rk3368_tsadc_data = { }; static const struct of_device_id of_rockchip_thermal_match[] = { + { + .compatible = "rockchip,rk3228-tsadc", + .data = (void *)&rk3228_tsadc_data, + }, { .compatible = "rockchip,rk3288-tsadc", .data = (void *)&rk3288_tsadc_data, From b0d70338bca22cb14367042a9d5cead116e7f2d9 Mon Sep 17 00:00:00 2001 From: Caesar Wang Date: Thu, 3 Dec 2015 16:48:43 +0800 Subject: [PATCH 09/14] thermal: rockchip: Support the RK3399 SoCs in thermal driver The RK3399 SoCs have two Temperature Sensors, channel 0 is for CPU. channel 1 is for GPU. Signed-off-by: Caesar Wang Signed-off-by: Eduardo Valentin --- drivers/thermal/rockchip_thermal.c | 66 ++++++++++++++++++++++++++++++ 1 file changed, 66 insertions(+) diff --git a/drivers/thermal/rockchip_thermal.c b/drivers/thermal/rockchip_thermal.c index e118e42c0326..b58e3fb9b311 100644 --- a/drivers/thermal/rockchip_thermal.c +++ b/drivers/thermal/rockchip_thermal.c @@ -292,6 +292,44 @@ static const struct tsadc_table v3_code_table[] = { {TSADCV3_DATA_MASK, 125000}, }; +static const struct tsadc_table v4_code_table[] = { + {TSADCV3_DATA_MASK, -40000}, + {431, -40000}, + {426, -35000}, + {421, -30000}, + {415, -25000}, + {410, -20000}, + {405, -15000}, + {399, -10000}, + {394, -5000}, + {389, 0}, + {383, 5000}, + {378, 10000}, + {373, 15000}, + {367, 20000}, + {362, 25000}, + {357, 30000}, + {351, 35000}, + {346, 40000}, + {340, 45000}, + {335, 50000}, + {330, 55000}, + {324, 60000}, + {319, 65000}, + {313, 70000}, + {308, 75000}, + {302, 80000}, + {297, 85000}, + {291, 90000}, + {286, 95000}, + {281, 100000}, + {275, 105000}, + {270, 110000}, + {264, 115000}, + {259, 120000}, + {253, 125000}, +}; + static u32 rk_tsadcv2_temp_to_code(struct chip_tsadc_table table, int temp) { @@ -555,6 +593,30 @@ static const struct rockchip_tsadc_chip rk3368_tsadc_data = { }, }; +static const struct rockchip_tsadc_chip rk3399_tsadc_data = { + .chn_id[SENSOR_CPU] = 0, /* cpu sensor is channel 0 */ + .chn_id[SENSOR_GPU] = 1, /* gpu sensor is channel 1 */ + .chn_num = 2, /* two channels for tsadc */ + + .tshut_mode = TSHUT_MODE_GPIO, /* default TSHUT via GPIO give PMIC */ + .tshut_polarity = TSHUT_LOW_ACTIVE, /* default TSHUT LOW ACTIVE */ + .tshut_temp = 95000, + + .initialize = rk_tsadcv2_initialize, + .irq_ack = rk_tsadcv1_irq_ack, + .control = rk_tsadcv2_control, + .get_temp = rk_tsadcv2_get_temp, + .set_tshut_temp = rk_tsadcv2_tshut_temp, + .set_tshut_mode = rk_tsadcv2_tshut_mode, + + .table = { + .id = v4_code_table, + .length = ARRAY_SIZE(v4_code_table), + .data_mask = TSADCV3_DATA_MASK, + .mode = ADC_DECREMENT, + }, +}; + static const struct of_device_id of_rockchip_thermal_match[] = { { .compatible = "rockchip,rk3228-tsadc", @@ -568,6 +630,10 @@ static const struct of_device_id of_rockchip_thermal_match[] = { .compatible = "rockchip,rk3368-tsadc", .data = (void *)&rk3368_tsadc_data, }, + { + .compatible = "rockchip,rk3399-tsadc", + .data = (void *)&rk3399_tsadc_data, + }, { /* end */ }, }; MODULE_DEVICE_TABLE(of, of_rockchip_thermal_match); From ca1e4558fcca68a5ac2a4e0f7834f788f9f4ac8f Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Tue, 15 Dec 2015 01:17:07 +0000 Subject: [PATCH 10/14] thermal: rcar: move rcar_thermal_dt_ids to upside This patch is prepare for of-thermal support. Signed-off-by: Kuninori Morimoto Signed-off-by: Eduardo Valentin --- drivers/thermal/rcar_thermal.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/thermal/rcar_thermal.c b/drivers/thermal/rcar_thermal.c index 13d01edc7a04..96707a6abd7f 100644 --- a/drivers/thermal/rcar_thermal.c +++ b/drivers/thermal/rcar_thermal.c @@ -81,6 +81,12 @@ struct rcar_thermal_priv { # define rcar_force_update_temp(priv) 0 #endif +static const struct of_device_id rcar_thermal_dt_ids[] = { + { .compatible = "renesas,rcar-thermal", }, + {}, +}; +MODULE_DEVICE_TABLE(of, rcar_thermal_dt_ids); + /* * basic functions */ @@ -484,12 +490,6 @@ error_unregister: return ret; } -static const struct of_device_id rcar_thermal_dt_ids[] = { - { .compatible = "renesas,rcar-thermal", }, - {}, -}; -MODULE_DEVICE_TABLE(of, rcar_thermal_dt_ids); - static struct platform_driver rcar_thermal_driver = { .driver = { .name = "rcar_thermal", From a1ade5653804b8eb9d14c5ba964da6d5c2f4cd30 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Tue, 15 Dec 2015 01:17:40 +0000 Subject: [PATCH 11/14] thermal: rcar: check every rcar_thermal_update_temp() return value Every rcar_thermal_update_temp() return value will be checked. And also, rcar_thermal_get_temp() always call rcar_thermal_update_temp() by this patch. Signed-off-by: Kuninori Morimoto Signed-off-by: Eduardo Valentin --- drivers/thermal/rcar_thermal.c | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/drivers/thermal/rcar_thermal.c b/drivers/thermal/rcar_thermal.c index 96707a6abd7f..b012d900c3f2 100644 --- a/drivers/thermal/rcar_thermal.c +++ b/drivers/thermal/rcar_thermal.c @@ -75,12 +75,6 @@ struct rcar_thermal_priv { #define rcar_has_irq_support(priv) ((priv)->common->base) #define rcar_id_to_shift(priv) ((priv)->id * 8) -#ifdef DEBUG -# define rcar_force_update_temp(priv) 1 -#else -# define rcar_force_update_temp(priv) 0 -#endif - static const struct of_device_id rcar_thermal_dt_ids[] = { { .compatible = "renesas,rcar-thermal", }, {}, @@ -209,9 +203,11 @@ err_out_unlock: static int rcar_thermal_get_temp(struct thermal_zone_device *zone, int *temp) { struct rcar_thermal_priv *priv = rcar_zone_to_priv(zone); + int ret; - if (!rcar_has_irq_support(priv) || rcar_force_update_temp(priv)) - rcar_thermal_update_temp(priv); + ret = rcar_thermal_update_temp(priv); + if (ret < 0) + return ret; mutex_lock(&priv->lock); *temp = MCELSIUS((priv->ctemp * 5) - 65); @@ -305,11 +301,15 @@ static void rcar_thermal_work(struct work_struct *work) { struct rcar_thermal_priv *priv; int cctemp, nctemp; + int ret; priv = container_of(work, struct rcar_thermal_priv, work.work); rcar_thermal_get_temp(priv->zone, &cctemp); - rcar_thermal_update_temp(priv); + ret = rcar_thermal_update_temp(priv); + if (ret < 0) + return; + rcar_thermal_irq_enable(priv); rcar_thermal_get_temp(priv->zone, &nctemp); @@ -447,7 +447,9 @@ static int rcar_thermal_probe(struct platform_device *pdev) mutex_init(&priv->lock); INIT_LIST_HEAD(&priv->list); INIT_DELAYED_WORK(&priv->work, rcar_thermal_work); - rcar_thermal_update_temp(priv); + ret = rcar_thermal_update_temp(priv); + if (ret < 0) + goto error_unregister; priv->zone = thermal_zone_device_register("rcar_thermal", 1, 0, priv, From ffbcdf8a759c6dde71c6c4f646a552f7637bcca7 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Tue, 15 Dec 2015 01:17:56 +0000 Subject: [PATCH 12/14] thermal: rcar: check irq possibility in rcar_thermal_irq_xxx() Current rcar thermal driver sometimes checks irq possibility when it calls rcar_thermal_irq_enable/disable(), but sometimes not. This patch checks it inside rcar_thermal_irq_enable/disable(). Signed-off-by: Kuninori Morimoto Signed-off-by: Eduardo Valentin --- drivers/thermal/rcar_thermal.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/thermal/rcar_thermal.c b/drivers/thermal/rcar_thermal.c index b012d900c3f2..fb81fd7e6b81 100644 --- a/drivers/thermal/rcar_thermal.c +++ b/drivers/thermal/rcar_thermal.c @@ -290,6 +290,9 @@ static void _rcar_thermal_irq_ctrl(struct rcar_thermal_priv *priv, int enable) unsigned long flags; u32 mask = 0x3 << rcar_id_to_shift(priv); /* enable Rising/Falling */ + if (!rcar_has_irq_support(priv)) + return; + spin_lock_irqsave(&common->lock, flags); rcar_thermal_common_bset(common, INTMSK, mask, enable ? 0 : mask); @@ -374,8 +377,7 @@ static int rcar_thermal_remove(struct platform_device *pdev) struct rcar_thermal_priv *priv; rcar_thermal_for_each_priv(priv, common) { - if (rcar_has_irq_support(priv)) - rcar_thermal_irq_disable(priv); + rcar_thermal_irq_disable(priv); thermal_zone_device_unregister(priv->zone); } @@ -461,8 +463,7 @@ static int rcar_thermal_probe(struct platform_device *pdev) goto error_unregister; } - if (rcar_has_irq_support(priv)) - rcar_thermal_irq_enable(priv); + rcar_thermal_irq_enable(priv); list_move_tail(&priv->list, &common->head); From 5440c40b900fa561add48a7e70e9c892f0551387 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Tue, 15 Dec 2015 01:18:13 +0000 Subject: [PATCH 13/14] thermal: rcar: rcar_thermal_get_temp() return error if strange temp Signed-off-by: Kuninori Morimoto Signed-off-by: Eduardo Valentin --- drivers/thermal/rcar_thermal.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/drivers/thermal/rcar_thermal.c b/drivers/thermal/rcar_thermal.c index fb81fd7e6b81..44b9c485157d 100644 --- a/drivers/thermal/rcar_thermal.c +++ b/drivers/thermal/rcar_thermal.c @@ -203,6 +203,7 @@ err_out_unlock: static int rcar_thermal_get_temp(struct thermal_zone_device *zone, int *temp) { struct rcar_thermal_priv *priv = rcar_zone_to_priv(zone); + int tmp; int ret; ret = rcar_thermal_update_temp(priv); @@ -210,9 +211,18 @@ static int rcar_thermal_get_temp(struct thermal_zone_device *zone, int *temp) return ret; mutex_lock(&priv->lock); - *temp = MCELSIUS((priv->ctemp * 5) - 65); + tmp = MCELSIUS((priv->ctemp * 5) - 65); mutex_unlock(&priv->lock); + if ((tmp < MCELSIUS(-45)) || (tmp > MCELSIUS(125))) { + struct device *dev = rcar_priv_to_dev(priv); + + dev_err(dev, "it couldn't measure temperature correctly\n"); + return -EIO; + } + + *temp = tmp; + return 0; } From ad74e46cb3ba9e706f91f3f71baf816d2d8e45db Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Tue, 15 Dec 2015 01:19:53 +0000 Subject: [PATCH 14/14] thermal: trip_point_temp_store() calls thermal_zone_device_update() trip_point_temp_store() updates trip temperature. It should call thermal_zone_device_update() immediately. Signed-off-by: Kuninori Morimoto Signed-off-by: Eduardo Valentin --- drivers/thermal/thermal_core.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c index d9e525cc9c1c..768fb10eb962 100644 --- a/drivers/thermal/thermal_core.c +++ b/drivers/thermal/thermal_core.c @@ -676,8 +676,12 @@ trip_point_temp_store(struct device *dev, struct device_attribute *attr, return -EINVAL; ret = tz->ops->set_trip_temp(tz, trip, temperature); + if (ret) + return ret; - return ret ? ret : count; + thermal_zone_device_update(tz); + + return count; } static ssize_t