diff options
author | Joonas Lahtinen <joonas.lahtinen@linux.intel.com> | 2018-03-01 12:14:24 +0300 |
---|---|---|
committer | Joonas Lahtinen <joonas.lahtinen@linux.intel.com> | 2018-03-01 12:14:24 +0300 |
commit | bba73071b6f71be0a101658d7c13866e30b264a6 (patch) | |
tree | 2a0ea1fc5fd975f1c2e9e50de5bb3cb2cb3cb5f7 /drivers/thermal | |
parent | c71b53cc66c5053ff3524a6132f8fc8199d618c3 (diff) | |
parent | f073d78eeb8efd85718e611c15f9a78647751dea (diff) | |
download | linux-bba73071b6f71be0a101658d7c13866e30b264a6.tar.xz |
Merge drm-next into drm-intel-next-queued (this time for real)
To pull in the HDCP changes, especially wait_for changes to drm/i915
that Chris wants to build on top of.
Signed-off-by: Joonas Lahtinen <joonas.lahtinen@linux.intel.com>
Diffstat (limited to 'drivers/thermal')
-rw-r--r-- | drivers/thermal/Kconfig | 4 | ||||
-rw-r--r-- | drivers/thermal/armada_thermal.c | 253 | ||||
-rw-r--r-- | drivers/thermal/cpu_cooling.c | 201 | ||||
-rw-r--r-- | drivers/thermal/hisi_thermal.c | 2 | ||||
-rw-r--r-- | drivers/thermal/imx_thermal.c | 74 | ||||
-rw-r--r-- | drivers/thermal/int340x_thermal/int3400_thermal.c | 12 | ||||
-rw-r--r-- | drivers/thermal/mtk_thermal.c | 9 | ||||
-rw-r--r-- | drivers/thermal/of-thermal.c | 1 | ||||
-rw-r--r-- | drivers/thermal/power_allocator.c | 2 | ||||
-rw-r--r-- | drivers/thermal/tegra/soctherm.c | 103 | ||||
-rw-r--r-- | drivers/thermal/thermal_hwmon.c | 20 | ||||
-rw-r--r-- | drivers/thermal/thermal_sysfs.c | 17 | ||||
-rw-r--r-- | drivers/thermal/x86_pkg_temp_thermal.c | 4 |
13 files changed, 333 insertions, 369 deletions
diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig index 315ae2926e20..b6adc54b96f1 100644 --- a/drivers/thermal/Kconfig +++ b/drivers/thermal/Kconfig @@ -301,13 +301,13 @@ config DB8500_THERMAL thermal zone if trip points reached. config ARMADA_THERMAL - tristate "Armada 370/XP thermal management" + tristate "Marvell EBU Armada SoCs thermal management" depends on ARCH_MVEBU || COMPILE_TEST depends on HAS_IOMEM depends on OF help Enable this option if you want to have support for thermal management - controller present in Armada 370 and Armada XP SoC. + controller present in Marvell EBU Armada SoCs (370,375,XP,38x,7K,8K). config DA9062_THERMAL tristate "DA9062/DA9061 Dialog Semiconductor thermal driver" diff --git a/drivers/thermal/armada_thermal.c b/drivers/thermal/armada_thermal.c index 706d74798cbe..4c275ec10ac5 100644 --- a/drivers/thermal/armada_thermal.c +++ b/drivers/thermal/armada_thermal.c @@ -1,5 +1,5 @@ /* - * Marvell Armada 370/XP thermal sensor driver + * Marvell EBU Armada SoCs thermal sensor driver * * Copyright (C) 2013 Marvell * @@ -23,8 +23,7 @@ #include <linux/platform_device.h> #include <linux/of_device.h> #include <linux/thermal.h> - -#define THERMAL_VALID_MASK 0x1 +#include <linux/iopoll.h> /* Thermal Manager Control and Status Register */ #define PMU_TDC0_SW_RST_MASK (0x1 << 1) @@ -39,14 +38,38 @@ #define A375_UNIT_CONTROL_MASK 0x7 #define A375_READOUT_INVERT BIT(15) #define A375_HW_RESETn BIT(8) -#define A380_HW_RESET BIT(8) + +/* Legacy bindings */ +#define LEGACY_CONTROL_MEM_LEN 0x4 + +/* Current bindings with the 2 control registers under the same memory area */ +#define LEGACY_CONTROL1_OFFSET 0x0 +#define CONTROL0_OFFSET 0x0 +#define CONTROL1_OFFSET 0x4 + +/* Errata fields */ +#define CONTROL0_TSEN_TC_TRIM_MASK 0x7 +#define CONTROL0_TSEN_TC_TRIM_VAL 0x3 + +/* TSEN refers to the temperature sensors within the AP */ +#define CONTROL0_TSEN_START BIT(0) +#define CONTROL0_TSEN_RESET BIT(1) +#define CONTROL0_TSEN_ENABLE BIT(2) + +/* EXT_TSEN refers to the external temperature sensors, out of the AP */ +#define CONTROL1_EXT_TSEN_SW_RESET BIT(7) +#define CONTROL1_EXT_TSEN_HW_RESETn BIT(8) + +#define STATUS_POLL_PERIOD_US 1000 +#define STATUS_POLL_TIMEOUT_US 100000 struct armada_thermal_data; /* Marvell EBU Thermal Sensor Dev Structure */ struct armada_thermal_priv { - void __iomem *sensor; - void __iomem *control; + void __iomem *status; + void __iomem *control0; + void __iomem *control1; struct armada_thermal_data *data; }; @@ -59,107 +82,142 @@ struct armada_thermal_data { bool (*is_valid)(struct armada_thermal_priv *); /* Formula coeficients: temp = (b - m * reg) / div */ - unsigned long coef_b; - unsigned long coef_m; - unsigned long coef_div; + s64 coef_b; + s64 coef_m; + u32 coef_div; bool inverted; + bool signed_sample; /* Register shift and mask to access the sensor temperature */ unsigned int temp_shift; unsigned int temp_mask; - unsigned int is_valid_shift; + u32 is_valid_bit; + bool needs_control0; }; static void armadaxp_init_sensor(struct platform_device *pdev, struct armada_thermal_priv *priv) { - unsigned long reg; + u32 reg; - reg = readl_relaxed(priv->control); + reg = readl_relaxed(priv->control1); reg |= PMU_TDC0_OTF_CAL_MASK; - writel(reg, priv->control); + writel(reg, priv->control1); /* Reference calibration value */ reg &= ~PMU_TDC0_REF_CAL_CNT_MASK; reg |= (0xf1 << PMU_TDC0_REF_CAL_CNT_OFFS); - writel(reg, priv->control); + writel(reg, priv->control1); /* Reset the sensor */ - reg = readl_relaxed(priv->control); - writel((reg | PMU_TDC0_SW_RST_MASK), priv->control); + reg = readl_relaxed(priv->control1); + writel((reg | PMU_TDC0_SW_RST_MASK), priv->control1); - writel(reg, priv->control); + writel(reg, priv->control1); /* Enable the sensor */ - reg = readl_relaxed(priv->sensor); + reg = readl_relaxed(priv->status); reg &= ~PMU_TM_DISABLE_MASK; - writel(reg, priv->sensor); + writel(reg, priv->status); } static void armada370_init_sensor(struct platform_device *pdev, struct armada_thermal_priv *priv) { - unsigned long reg; + u32 reg; - reg = readl_relaxed(priv->control); + reg = readl_relaxed(priv->control1); reg |= PMU_TDC0_OTF_CAL_MASK; - writel(reg, priv->control); + writel(reg, priv->control1); /* Reference calibration value */ reg &= ~PMU_TDC0_REF_CAL_CNT_MASK; reg |= (0xf1 << PMU_TDC0_REF_CAL_CNT_OFFS); - writel(reg, priv->control); + writel(reg, priv->control1); reg &= ~PMU_TDC0_START_CAL_MASK; - writel(reg, priv->control); + writel(reg, priv->control1); - mdelay(10); + msleep(10); } static void armada375_init_sensor(struct platform_device *pdev, struct armada_thermal_priv *priv) { - unsigned long reg; + u32 reg; - reg = readl(priv->control + 4); + reg = readl(priv->control1); reg &= ~(A375_UNIT_CONTROL_MASK << A375_UNIT_CONTROL_SHIFT); reg &= ~A375_READOUT_INVERT; reg &= ~A375_HW_RESETn; - writel(reg, priv->control + 4); - mdelay(20); + writel(reg, priv->control1); + msleep(20); reg |= A375_HW_RESETn; - writel(reg, priv->control + 4); - mdelay(50); + writel(reg, priv->control1); + msleep(50); +} + +static void armada_wait_sensor_validity(struct armada_thermal_priv *priv) +{ + u32 reg; + + readl_relaxed_poll_timeout(priv->status, reg, + reg & priv->data->is_valid_bit, + STATUS_POLL_PERIOD_US, + STATUS_POLL_TIMEOUT_US); } static void armada380_init_sensor(struct platform_device *pdev, struct armada_thermal_priv *priv) { - unsigned long reg = readl_relaxed(priv->control); - - /* Reset hardware once */ - if (!(reg & A380_HW_RESET)) { - reg |= A380_HW_RESET; - writel(reg, priv->control); - mdelay(10); + u32 reg = readl_relaxed(priv->control1); + + /* Disable the HW/SW reset */ + reg |= CONTROL1_EXT_TSEN_HW_RESETn; + reg &= ~CONTROL1_EXT_TSEN_SW_RESET; + writel(reg, priv->control1); + + /* Set Tsen Tc Trim to correct default value (errata #132698) */ + if (priv->control0) { + reg = readl_relaxed(priv->control0); + reg &= ~CONTROL0_TSEN_TC_TRIM_MASK; + reg |= CONTROL0_TSEN_TC_TRIM_VAL; + writel(reg, priv->control0); } + + /* Wait the sensors to be valid or the core will warn the user */ + armada_wait_sensor_validity(priv); +} + +static void armada_ap806_init_sensor(struct platform_device *pdev, + struct armada_thermal_priv *priv) +{ + u32 reg; + + reg = readl_relaxed(priv->control0); + reg &= ~CONTROL0_TSEN_RESET; + reg |= CONTROL0_TSEN_START | CONTROL0_TSEN_ENABLE; + writel(reg, priv->control0); + + /* Wait the sensors to be valid or the core will warn the user */ + armada_wait_sensor_validity(priv); } static bool armada_is_valid(struct armada_thermal_priv *priv) { - unsigned long reg = readl_relaxed(priv->sensor); + u32 reg = readl_relaxed(priv->status); - return (reg >> priv->data->is_valid_shift) & THERMAL_VALID_MASK; + return reg & priv->data->is_valid_bit; } static int armada_get_temp(struct thermal_zone_device *thermal, - int *temp) + int *temp) { struct armada_thermal_priv *priv = thermal->devdata; - unsigned long reg; - unsigned long m, b, div; + u32 reg, div; + s64 sample, b, m; /* Valid check */ if (priv->data->is_valid && !priv->data->is_valid(priv)) { @@ -168,8 +226,13 @@ static int armada_get_temp(struct thermal_zone_device *thermal, return -EIO; } - reg = readl_relaxed(priv->sensor); + reg = readl_relaxed(priv->status); reg = (reg >> priv->data->temp_shift) & priv->data->temp_mask; + if (priv->data->signed_sample) + /* The most significant bit is the sign bit */ + sample = sign_extend32(reg, fls(priv->data->temp_mask) - 1); + else + sample = reg; /* Get formula coeficients */ b = priv->data->coef_b; @@ -177,9 +240,10 @@ static int armada_get_temp(struct thermal_zone_device *thermal, div = priv->data->coef_div; if (priv->data->inverted) - *temp = ((m * reg) - b) / div; + *temp = div_s64((m * sample) - b, div); else - *temp = (b - (m * reg)) / div; + *temp = div_s64(b - (m * sample), div); + return 0; } @@ -191,45 +255,73 @@ static const struct armada_thermal_data armadaxp_data = { .init_sensor = armadaxp_init_sensor, .temp_shift = 10, .temp_mask = 0x1ff, - .coef_b = 3153000000UL, - .coef_m = 10000000UL, + .coef_b = 3153000000ULL, + .coef_m = 10000000ULL, .coef_div = 13825, }; static const struct armada_thermal_data armada370_data = { .is_valid = armada_is_valid, .init_sensor = armada370_init_sensor, - .is_valid_shift = 9, + .is_valid_bit = BIT(9), .temp_shift = 10, .temp_mask = 0x1ff, - .coef_b = 3153000000UL, - .coef_m = 10000000UL, + .coef_b = 3153000000ULL, + .coef_m = 10000000ULL, .coef_div = 13825, }; static const struct armada_thermal_data armada375_data = { .is_valid = armada_is_valid, .init_sensor = armada375_init_sensor, - .is_valid_shift = 10, + .is_valid_bit = BIT(10), .temp_shift = 0, .temp_mask = 0x1ff, - .coef_b = 3171900000UL, - .coef_m = 10000000UL, + .coef_b = 3171900000ULL, + .coef_m = 10000000ULL, .coef_div = 13616, + .needs_control0 = true, }; static const struct armada_thermal_data armada380_data = { .is_valid = armada_is_valid, .init_sensor = armada380_init_sensor, - .is_valid_shift = 10, + .is_valid_bit = BIT(10), .temp_shift = 0, .temp_mask = 0x3ff, - .coef_b = 1172499100UL, - .coef_m = 2000096UL, + .coef_b = 1172499100ULL, + .coef_m = 2000096ULL, .coef_div = 4201, .inverted = true, }; +static const struct armada_thermal_data armada_ap806_data = { + .is_valid = armada_is_valid, + .init_sensor = armada_ap806_init_sensor, + .is_valid_bit = BIT(16), + .temp_shift = 0, + .temp_mask = 0x3ff, + .coef_b = -150000LL, + .coef_m = 423ULL, + .coef_div = 1, + .inverted = true, + .signed_sample = true, + .needs_control0 = true, +}; + +static const struct armada_thermal_data armada_cp110_data = { + .is_valid = armada_is_valid, + .init_sensor = armada380_init_sensor, + .is_valid_bit = BIT(10), + .temp_shift = 0, + .temp_mask = 0x3ff, + .coef_b = 1172499100ULL, + .coef_m = 2000096ULL, + .coef_div = 4201, + .inverted = true, + .needs_control0 = true, +}; + static const struct of_device_id armada_thermal_id_table[] = { { .compatible = "marvell,armadaxp-thermal", @@ -248,6 +340,14 @@ static const struct of_device_id armada_thermal_id_table[] = { .data = &armada380_data, }, { + .compatible = "marvell,armada-ap806-thermal", + .data = &armada_ap806_data, + }, + { + .compatible = "marvell,armada-cp110-thermal", + .data = &armada_cp110_data, + }, + { /* sentinel */ }, }; @@ -255,6 +355,7 @@ MODULE_DEVICE_TABLE(of, armada_thermal_id_table); static int armada_thermal_probe(struct platform_device *pdev) { + void __iomem *control = NULL; struct thermal_zone_device *thermal; const struct of_device_id *match; struct armada_thermal_priv *priv; @@ -269,20 +370,40 @@ static int armada_thermal_probe(struct platform_device *pdev) return -ENOMEM; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - priv->sensor = devm_ioremap_resource(&pdev->dev, res); - if (IS_ERR(priv->sensor)) - return PTR_ERR(priv->sensor); + priv->status = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(priv->status)) + return PTR_ERR(priv->status); res = platform_get_resource(pdev, IORESOURCE_MEM, 1); - priv->control = devm_ioremap_resource(&pdev->dev, res); - if (IS_ERR(priv->control)) - return PTR_ERR(priv->control); + control = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(control)) + return PTR_ERR(control); priv->data = (struct armada_thermal_data *)match->data; + + /* + * Legacy DT bindings only described "control1" register (also referred + * as "control MSB" on old documentation). New bindings cover + * "control0/control LSB" and "control1/control MSB" registers within + * the same resource, which is then of size 8 instead of 4. + */ + if (resource_size(res) == LEGACY_CONTROL_MEM_LEN) { + /* ->control0 unavailable in this configuration */ + if (priv->data->needs_control0) { + dev_err(&pdev->dev, "No access to control0 register\n"); + return -EINVAL; + } + + priv->control1 = control + LEGACY_CONTROL1_OFFSET; + } else { + priv->control0 = control + CONTROL0_OFFSET; + priv->control1 = control + CONTROL1_OFFSET; + } + priv->data->init_sensor(pdev, priv); - thermal = thermal_zone_device_register("armada_thermal", 0, 0, - priv, &ops, NULL, 0, 0); + thermal = thermal_zone_device_register(dev_name(&pdev->dev), 0, 0, priv, + &ops, NULL, 0, 0); if (IS_ERR(thermal)) { dev_err(&pdev->dev, "Failed to register thermal zone device\n"); @@ -316,5 +437,5 @@ static struct platform_driver armada_thermal_driver = { module_platform_driver(armada_thermal_driver); MODULE_AUTHOR("Ezequiel Garcia <ezequiel.garcia@free-electrons.com>"); -MODULE_DESCRIPTION("Armada 370/XP thermal driver"); +MODULE_DESCRIPTION("Marvell EBU Armada SoCs thermal driver"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/thermal/cpu_cooling.c b/drivers/thermal/cpu_cooling.c index dc63aba092e4..dfd23245f778 100644 --- a/drivers/thermal/cpu_cooling.c +++ b/drivers/thermal/cpu_cooling.c @@ -88,7 +88,6 @@ struct time_in_idle { * @policy: cpufreq policy. * @node: list_head to link all cpufreq_cooling_device together. * @idle_time: idle time stats - * @plat_get_static_power: callback to calculate the static power * * This structure is required for keeping information of each registered * cpufreq_cooling_device. @@ -104,7 +103,6 @@ struct cpufreq_cooling_device { struct cpufreq_policy *policy; struct list_head node; struct time_in_idle *idle_time; - get_static_t plat_get_static_power; }; static DEFINE_IDA(cpufreq_ida); @@ -319,60 +317,6 @@ static u32 get_load(struct cpufreq_cooling_device *cpufreq_cdev, int cpu, } /** - * get_static_power() - calculate the static power consumed by the cpus - * @cpufreq_cdev: struct &cpufreq_cooling_device for this cpu cdev - * @tz: thermal zone device in which we're operating - * @freq: frequency in KHz - * @power: pointer in which to store the calculated static power - * - * Calculate the static power consumed by the cpus described by - * @cpu_actor running at frequency @freq. This function relies on a - * platform specific function that should have been provided when the - * actor was registered. If it wasn't, the static power is assumed to - * be negligible. The calculated static power is stored in @power. - * - * Return: 0 on success, -E* on failure. - */ -static int get_static_power(struct cpufreq_cooling_device *cpufreq_cdev, - struct thermal_zone_device *tz, unsigned long freq, - u32 *power) -{ - struct dev_pm_opp *opp; - unsigned long voltage; - struct cpufreq_policy *policy = cpufreq_cdev->policy; - struct cpumask *cpumask = policy->related_cpus; - unsigned long freq_hz = freq * 1000; - struct device *dev; - - if (!cpufreq_cdev->plat_get_static_power) { - *power = 0; - return 0; - } - - dev = get_cpu_device(policy->cpu); - WARN_ON(!dev); - - opp = dev_pm_opp_find_freq_exact(dev, freq_hz, true); - if (IS_ERR(opp)) { - dev_warn_ratelimited(dev, "Failed to find OPP for frequency %lu: %ld\n", - freq_hz, PTR_ERR(opp)); - return -EINVAL; - } - - voltage = dev_pm_opp_get_voltage(opp); - dev_pm_opp_put(opp); - - if (voltage == 0) { - dev_err_ratelimited(dev, "Failed to get voltage for frequency %lu\n", - freq_hz); - return -EINVAL; - } - - return cpufreq_cdev->plat_get_static_power(cpumask, tz->passive_delay, - voltage, power); -} - -/** * get_dynamic_power() - calculate the dynamic power * @cpufreq_cdev: &cpufreq_cooling_device for this cdev * @freq: current frequency @@ -491,8 +435,8 @@ static int cpufreq_get_requested_power(struct thermal_cooling_device *cdev, u32 *power) { unsigned long freq; - int i = 0, cpu, ret; - u32 static_power, dynamic_power, total_load = 0; + int i = 0, cpu; + u32 total_load = 0; struct cpufreq_cooling_device *cpufreq_cdev = cdev->devdata; struct cpufreq_policy *policy = cpufreq_cdev->policy; u32 *load_cpu = NULL; @@ -522,22 +466,15 @@ static int cpufreq_get_requested_power(struct thermal_cooling_device *cdev, cpufreq_cdev->last_load = total_load; - dynamic_power = get_dynamic_power(cpufreq_cdev, freq); - ret = get_static_power(cpufreq_cdev, tz, freq, &static_power); - if (ret) { - kfree(load_cpu); - return ret; - } + *power = get_dynamic_power(cpufreq_cdev, freq); if (load_cpu) { trace_thermal_power_cpu_get_power(policy->related_cpus, freq, - load_cpu, i, dynamic_power, - static_power); + load_cpu, i, *power); kfree(load_cpu); } - *power = static_power + dynamic_power; return 0; } @@ -561,8 +498,6 @@ static int cpufreq_state2power(struct thermal_cooling_device *cdev, unsigned long state, u32 *power) { unsigned int freq, num_cpus; - u32 static_power, dynamic_power; - int ret; struct cpufreq_cooling_device *cpufreq_cdev = cdev->devdata; /* Request state should be less than max_level */ @@ -572,13 +507,9 @@ static int cpufreq_state2power(struct thermal_cooling_device *cdev, num_cpus = cpumask_weight(cpufreq_cdev->policy->cpus); freq = cpufreq_cdev->freq_table[state].frequency; - dynamic_power = cpu_freq_to_power(cpufreq_cdev, freq) * num_cpus; - ret = get_static_power(cpufreq_cdev, tz, freq, &static_power); - if (ret) - return ret; + *power = cpu_freq_to_power(cpufreq_cdev, freq) * num_cpus; - *power = static_power + dynamic_power; - return ret; + return 0; } /** @@ -606,21 +537,14 @@ static int cpufreq_power2state(struct thermal_cooling_device *cdev, unsigned long *state) { unsigned int cur_freq, target_freq; - int ret; - s32 dyn_power; - u32 last_load, normalised_power, static_power; + u32 last_load, normalised_power; struct cpufreq_cooling_device *cpufreq_cdev = cdev->devdata; struct cpufreq_policy *policy = cpufreq_cdev->policy; cur_freq = cpufreq_quick_get(policy->cpu); - ret = get_static_power(cpufreq_cdev, tz, cur_freq, &static_power); - if (ret) - return ret; - - dyn_power = power - static_power; - dyn_power = dyn_power > 0 ? dyn_power : 0; + power = power > 0 ? power : 0; last_load = cpufreq_cdev->last_load ?: 1; - normalised_power = (dyn_power * 100) / last_load; + normalised_power = (power * 100) / last_load; target_freq = cpu_power_to_freq(cpufreq_cdev, normalised_power); *state = get_level(cpufreq_cdev, target_freq); @@ -671,8 +595,6 @@ static unsigned int find_next_max(struct cpufreq_frequency_table *table, * @policy: cpufreq policy * Normally this should be same as cpufreq policy->related_cpus. * @capacitance: dynamic power coefficient for these cpus - * @plat_static_func: function to calculate the static power consumed by these - * cpus (optional) * * This interface function registers the cpufreq cooling device with the name * "thermal-cpufreq-%x". This api can support multiple instances of cpufreq @@ -684,8 +606,7 @@ static unsigned int find_next_max(struct cpufreq_frequency_table *table, */ static struct thermal_cooling_device * __cpufreq_cooling_register(struct device_node *np, - struct cpufreq_policy *policy, u32 capacitance, - get_static_t plat_static_func) + struct cpufreq_policy *policy, u32 capacitance) { struct thermal_cooling_device *cdev; struct cpufreq_cooling_device *cpufreq_cdev; @@ -755,8 +676,6 @@ __cpufreq_cooling_register(struct device_node *np, } if (capacitance) { - cpufreq_cdev->plat_get_static_power = plat_static_func; - ret = update_freq_table(cpufreq_cdev, capacitance); if (ret) { cdev = ERR_PTR(ret); @@ -813,13 +732,12 @@ free_cdev: struct thermal_cooling_device * cpufreq_cooling_register(struct cpufreq_policy *policy) { - return __cpufreq_cooling_register(NULL, policy, 0, NULL); + return __cpufreq_cooling_register(NULL, policy, 0); } EXPORT_SYMBOL_GPL(cpufreq_cooling_register); /** * of_cpufreq_cooling_register - function to create cpufreq cooling device. - * @np: a valid struct device_node to the cooling device device tree node * @policy: cpufreq policy * * This interface function registers the cpufreq cooling device with the name @@ -827,86 +745,45 @@ EXPORT_SYMBOL_GPL(cpufreq_cooling_register); * cooling devices. Using this API, the cpufreq cooling device will be * linked to the device tree node provided. * - * Return: a valid struct thermal_cooling_device pointer on success, - * on failure, it returns a corresponding ERR_PTR(). - */ -struct thermal_cooling_device * -of_cpufreq_cooling_register(struct device_node *np, - struct cpufreq_policy *policy) -{ - if (!np) - return ERR_PTR(-EINVAL); - - return __cpufreq_cooling_register(np, policy, 0, NULL); -} -EXPORT_SYMBOL_GPL(of_cpufreq_cooling_register); - -/** - * cpufreq_power_cooling_register() - create cpufreq cooling device with power extensions - * @policy: cpufreq policy - * @capacitance: dynamic power coefficient for these cpus - * @plat_static_func: function to calculate the static power consumed by these - * cpus (optional) - * - * This interface function registers the cpufreq cooling device with - * the name "thermal-cpufreq-%x". This api can support multiple - * instances of cpufreq cooling devices. Using this function, the - * cooling device will implement the power extensions by using a - * simple cpu power model. The cpus must have registered their OPPs - * using the OPP library. - * - * An optional @plat_static_func may be provided to calculate the - * static power consumed by these cpus. If the platform's static - * power consumption is unknown or negligible, make it NULL. - * - * Return: a valid struct thermal_cooling_device pointer on success, - * on failure, it returns a corresponding ERR_PTR(). - */ -struct thermal_cooling_device * -cpufreq_power_cooling_register(struct cpufreq_policy *policy, u32 capacitance, - get_static_t plat_static_func) -{ - return __cpufreq_cooling_register(NULL, policy, capacitance, - plat_static_func); -} -EXPORT_SYMBOL(cpufreq_power_cooling_register); - -/** - * of_cpufreq_power_cooling_register() - create cpufreq cooling device with power extensions - * @np: a valid struct device_node to the cooling device device tree node - * @policy: cpufreq policy - * @capacitance: dynamic power coefficient for these cpus - * @plat_static_func: function to calculate the static power consumed by these - * cpus (optional) - * - * This interface function registers the cpufreq cooling device with - * the name "thermal-cpufreq-%x". This api can support multiple - * instances of cpufreq cooling devices. Using this API, the cpufreq - * cooling device will be linked to the device tree node provided. * Using this function, the cooling device will implement the power * extensions by using a simple cpu power model. The cpus must have * registered their OPPs using the OPP library. * - * An optional @plat_static_func may be provided to calculate the - * static power consumed by these cpus. If the platform's static - * power consumption is unknown or negligible, make it NULL. + * It also takes into account, if property present in policy CPU node, the + * static power consumed by the cpu. * * Return: a valid struct thermal_cooling_device pointer on success, - * on failure, it returns a corresponding ERR_PTR(). + * and NULL on failure. */ struct thermal_cooling_device * -of_cpufreq_power_cooling_register(struct device_node *np, - struct cpufreq_policy *policy, - u32 capacitance, - get_static_t plat_static_func) +of_cpufreq_cooling_register(struct cpufreq_policy *policy) { - if (!np) - return ERR_PTR(-EINVAL); + struct device_node *np = of_get_cpu_node(policy->cpu, NULL); + struct thermal_cooling_device *cdev = NULL; + u32 capacitance = 0; + + if (!np) { + pr_err("cpu_cooling: OF node not available for cpu%d\n", + policy->cpu); + return NULL; + } + + if (of_find_property(np, "#cooling-cells", NULL)) { + of_property_read_u32(np, "dynamic-power-coefficient", + &capacitance); - return __cpufreq_cooling_register(np, policy, capacitance, - plat_static_func); + cdev = __cpufreq_cooling_register(np, policy, capacitance); + if (IS_ERR(cdev)) { + pr_err("cpu_cooling: cpu%d is not running as cooling device: %ld\n", + policy->cpu, PTR_ERR(cdev)); + cdev = NULL; + } + } + + of_node_put(np); + return cdev; } -EXPORT_SYMBOL(of_cpufreq_power_cooling_register); +EXPORT_SYMBOL_GPL(of_cpufreq_cooling_register); /** * cpufreq_cooling_unregister - function to remove cpufreq cooling device. diff --git a/drivers/thermal/hisi_thermal.c b/drivers/thermal/hisi_thermal.c index 2d855a96cdd9..761d0559c268 100644 --- a/drivers/thermal/hisi_thermal.c +++ b/drivers/thermal/hisi_thermal.c @@ -527,7 +527,7 @@ static void hisi_thermal_toggle_sensor(struct hisi_thermal_sensor *sensor, static int hisi_thermal_probe(struct platform_device *pdev) { struct hisi_thermal_data *data; - int const (*platform_probe)(struct hisi_thermal_data *); + int (*platform_probe)(struct hisi_thermal_data *); struct device *dev = &pdev->dev; int ret; diff --git a/drivers/thermal/imx_thermal.c b/drivers/thermal/imx_thermal.c index e7d4ffc3de7f..a67781b7a0b2 100644 --- a/drivers/thermal/imx_thermal.c +++ b/drivers/thermal/imx_thermal.c @@ -70,10 +70,6 @@ enum imx_thermal_trip { #define IMX_POLLING_DELAY 2000 /* millisecond */ #define IMX_PASSIVE_DELAY 1000 -#define FACTOR0 10000000 -#define FACTOR1 15976 -#define FACTOR2 4297157 - #define TEMPMON_IMX6Q 1 #define TEMPMON_IMX6SX 2 @@ -347,78 +343,74 @@ static struct thermal_zone_device_ops imx_tz_ops = { .set_trip_temp = imx_set_trip_temp, }; -static int imx_init_calib(struct platform_device *pdev, u32 val) +static int imx_init_calib(struct platform_device *pdev, u32 ocotp_ana1) { struct imx_thermal_data *data = platform_get_drvdata(pdev); - int t1, n1; + int n1; u64 temp64; - if (val == 0 || val == ~0) { + if (ocotp_ana1 == 0 || ocotp_ana1 == ~0) { dev_err(&pdev->dev, "invalid sensor calibration data\n"); return -EINVAL; } /* - * Sensor data layout: - * [31:20] - sensor value @ 25C - * Use universal formula now and only need sensor value @ 25C - * slope = 0.4297157 - (0.0015976 * 25C fuse) + * The sensor is calibrated at 25 °C (aka T1) and the value measured + * (aka N1) at this temperature is provided in bits [31:20] in the + * i.MX's OCOTP value ANA1. + * To find the actual temperature T, the following formula has to be used + * when reading value n from the sensor: + * + * T = T1 + (N - N1) / (0.4148468 - 0.0015423 * N1) °C + 3.580661 °C + * = [T1' - N1 / (0.4148468 - 0.0015423 * N1) °C] + N / (0.4148468 - 0.0015423 * N1) °C + * = [T1' + N1 / (0.0015423 * N1 - 0.4148468) °C] - N / (0.0015423 * N1 - 0.4148468) °C + * = c2 - c1 * N + * + * with + * + * T1' = 28.580661 °C + * c1 = 1 / (0.0015423 * N1 - 0.4297157) °C + * c2 = T1' + N1 / (0.0015423 * N1 - 0.4148468) °C + * = T1' + N1 * c1 */ - n1 = val >> 20; - t1 = 25; /* t1 always 25C */ + n1 = ocotp_ana1 >> 20; - /* - * Derived from linear interpolation: - * slope = 0.4297157 - (0.0015976 * 25C fuse) - * slope = (FACTOR2 - FACTOR1 * n1) / FACTOR0 - * (Nmeas - n1) / (Tmeas - t1) = slope - * We want to reduce this down to the minimum computation necessary - * for each temperature read. Also, we want Tmeas in millicelsius - * and we don't want to lose precision from integer division. So... - * Tmeas = (Nmeas - n1) / slope + t1 - * milli_Tmeas = 1000 * (Nmeas - n1) / slope + 1000 * t1 - * milli_Tmeas = -1000 * (n1 - Nmeas) / slope + 1000 * t1 - * Let constant c1 = (-1000 / slope) - * milli_Tmeas = (n1 - Nmeas) * c1 + 1000 * t1 - * Let constant c2 = n1 *c1 + 1000 * t1 - * milli_Tmeas = c2 - Nmeas * c1 - */ - temp64 = FACTOR0; - temp64 *= 1000; - do_div(temp64, FACTOR1 * n1 - FACTOR2); + temp64 = 10000000; /* use 10^7 as fixed point constant for values in formula */ + temp64 *= 1000; /* to get result in °mC */ + do_div(temp64, 15423 * n1 - 4148468); data->c1 = temp64; - data->c2 = n1 * data->c1 + 1000 * t1; + data->c2 = n1 * data->c1 + 28581; return 0; } -static void imx_init_temp_grade(struct platform_device *pdev, u32 val) +static void imx_init_temp_grade(struct platform_device *pdev, u32 ocotp_mem0) { struct imx_thermal_data *data = platform_get_drvdata(pdev); /* The maximum die temp is specified by the Temperature Grade */ - switch ((val >> 6) & 0x3) { - case 0: /* Commercial (0 to 95C) */ + switch ((ocotp_mem0 >> 6) & 0x3) { + case 0: /* Commercial (0 to 95 °C) */ data->temp_grade = "Commercial"; data->temp_max = 95000; break; - case 1: /* Extended Commercial (-20 to 105C) */ + case 1: /* Extended Commercial (-20 °C to 105 °C) */ data->temp_grade = "Extended Commercial"; data->temp_max = 105000; break; - case 2: /* Industrial (-40 to 105C) */ + case 2: /* Industrial (-40 °C to 105 °C) */ data->temp_grade = "Industrial"; data->temp_max = 105000; break; - case 3: /* Automotive (-40 to 125C) */ + case 3: /* Automotive (-40 °C to 125 °C) */ data->temp_grade = "Automotive"; data->temp_max = 125000; break; } /* - * Set the critical trip point at 5C under max - * Set the passive trip point at 10C under max (can change via sysfs) + * Set the critical trip point at 5 °C under max + * Set the passive trip point at 10 °C under max (changeable via sysfs) */ data->temp_critical = data->temp_max - (1000 * 5); data->temp_passive = data->temp_max - (1000 * 10); diff --git a/drivers/thermal/int340x_thermal/int3400_thermal.c b/drivers/thermal/int340x_thermal/int3400_thermal.c index 8ee38f55c7f3..e26b01c05e82 100644 --- a/drivers/thermal/int340x_thermal/int3400_thermal.c +++ b/drivers/thermal/int340x_thermal/int3400_thermal.c @@ -211,7 +211,7 @@ static void int3400_notify(acpi_handle handle, thermal_prop); break; default: - dev_err(&priv->adev->dev, "Unsupported event [0x%x]\n", event); + /* Ignore unknown notification codes sent to INT3400 device */ break; } } @@ -319,17 +319,21 @@ static int int3400_thermal_probe(struct platform_device *pdev) result = sysfs_create_group(&pdev->dev.kobj, &uuid_attribute_group); if (result) - goto free_zone; + goto free_rel_misc; result = acpi_install_notify_handler( priv->adev->handle, ACPI_DEVICE_NOTIFY, int3400_notify, (void *)priv); if (result) - goto free_zone; + goto free_sysfs; return 0; -free_zone: +free_sysfs: + sysfs_remove_group(&pdev->dev.kobj, &uuid_attribute_group); +free_rel_misc: + if (!priv->rel_misc_dev_res) + acpi_thermal_rel_misc_device_remove(priv->adev->handle); thermal_zone_device_unregister(priv->thermal); free_art_trt: kfree(priv->trts); diff --git a/drivers/thermal/mtk_thermal.c b/drivers/thermal/mtk_thermal.c index 1e61c09153c9..c75661a3801a 100644 --- a/drivers/thermal/mtk_thermal.c +++ b/drivers/thermal/mtk_thermal.c @@ -32,15 +32,10 @@ #include <linux/types.h> /* AUXADC Registers */ -#define AUXADC_CON0_V 0x000 -#define AUXADC_CON1_V 0x004 #define AUXADC_CON1_SET_V 0x008 #define AUXADC_CON1_CLR_V 0x00c #define AUXADC_CON2_V 0x010 #define AUXADC_DATA(channel) (0x14 + (channel) * 4) -#define AUXADC_MISC_V 0x094 - -#define AUXADC_CON1_CHANNEL(x) BIT(x) #define APMIXED_SYS_TS_CON1 0x604 @@ -158,8 +153,6 @@ /* The number of sensing points per bank */ #define MT2712_NUM_SENSORS_PER_ZONE 4 -#define THERMAL_NAME "mtk-thermal" - struct mtk_thermal; struct thermal_bank_cfg { @@ -765,7 +758,7 @@ static struct platform_driver mtk_thermal_driver = { .probe = mtk_thermal_probe, .remove = mtk_thermal_remove, .driver = { - .name = THERMAL_NAME, + .name = "mtk-thermal", .of_match_table = mtk_thermal_of_match, }, }; diff --git a/drivers/thermal/of-thermal.c b/drivers/thermal/of-thermal.c index d04ec3b9e5ff..e09f0354a4bc 100644 --- a/drivers/thermal/of-thermal.c +++ b/drivers/thermal/of-thermal.c @@ -30,7 +30,6 @@ #include <linux/err.h> #include <linux/export.h> #include <linux/string.h> -#include <linux/thermal.h> #include "thermal_core.h" diff --git a/drivers/thermal/power_allocator.c b/drivers/thermal/power_allocator.c index b4d3116cfdaf..3055f9a12a17 100644 --- a/drivers/thermal/power_allocator.c +++ b/drivers/thermal/power_allocator.c @@ -523,6 +523,7 @@ static void allow_maximum_power(struct thermal_zone_device *tz) struct thermal_instance *instance; struct power_allocator_params *params = tz->governor_data; + mutex_lock(&tz->lock); list_for_each_entry(instance, &tz->thermal_instances, tz_node) { if ((instance->trip != params->trip_max_desired_temperature) || (!cdev_is_power_actor(instance->cdev))) @@ -534,6 +535,7 @@ static void allow_maximum_power(struct thermal_zone_device *tz) mutex_unlock(&instance->cdev->lock); thermal_cdev_update(instance->cdev); } + mutex_unlock(&tz->lock); } /** diff --git a/drivers/thermal/tegra/soctherm.c b/drivers/thermal/tegra/soctherm.c index 075db1de5e53..455b58ce2652 100644 --- a/drivers/thermal/tegra/soctherm.c +++ b/drivers/thermal/tegra/soctherm.c @@ -341,62 +341,6 @@ static int tegra_thermctl_get_temp(void *data, int *out_temp) return 0; } -static int -thermtrip_program(struct device *dev, const struct tegra_tsensor_group *sg, - int trip_temp); -static int -throttrip_program(struct device *dev, const struct tegra_tsensor_group *sg, - struct soctherm_throt_cfg *stc, int trip_temp); -static struct soctherm_throt_cfg * -find_throttle_cfg_by_name(struct tegra_soctherm *ts, const char *name); - -static int tegra_thermctl_set_trip_temp(void *data, int trip, int temp) -{ - struct tegra_thermctl_zone *zone = data; - struct thermal_zone_device *tz = zone->tz; - struct tegra_soctherm *ts = zone->ts; - const struct tegra_tsensor_group *sg = zone->sg; - struct device *dev = zone->dev; - enum thermal_trip_type type; - int ret; - - if (!tz) - return -EINVAL; - - ret = tz->ops->get_trip_type(tz, trip, &type); - if (ret) - return ret; - - if (type == THERMAL_TRIP_CRITICAL) { - return thermtrip_program(dev, sg, temp); - } else if (type == THERMAL_TRIP_HOT) { - int i; - - for (i = 0; i < THROTTLE_SIZE; i++) { - struct thermal_cooling_device *cdev; - struct soctherm_throt_cfg *stc; - - if (!ts->throt_cfgs[i].init) - continue; - - cdev = ts->throt_cfgs[i].cdev; - if (get_thermal_instance(tz, cdev, trip)) - stc = find_throttle_cfg_by_name(ts, cdev->type); - else - continue; - - return throttrip_program(dev, sg, stc, temp); - } - } - - return 0; -} - -static const struct thermal_zone_of_device_ops tegra_of_thermal_ops = { - .get_temp = tegra_thermctl_get_temp, - .set_trip_temp = tegra_thermctl_set_trip_temp, -}; - /** * enforce_temp_range() - check and enforce temperature range [min, max] * @trip_temp: the trip temperature to check @@ -527,6 +471,53 @@ find_throttle_cfg_by_name(struct tegra_soctherm *ts, const char *name) return NULL; } +static int tegra_thermctl_set_trip_temp(void *data, int trip, int temp) +{ + struct tegra_thermctl_zone *zone = data; + struct thermal_zone_device *tz = zone->tz; + struct tegra_soctherm *ts = zone->ts; + const struct tegra_tsensor_group *sg = zone->sg; + struct device *dev = zone->dev; + enum thermal_trip_type type; + int ret; + + if (!tz) + return -EINVAL; + + ret = tz->ops->get_trip_type(tz, trip, &type); + if (ret) + return ret; + + if (type == THERMAL_TRIP_CRITICAL) { + return thermtrip_program(dev, sg, temp); + } else if (type == THERMAL_TRIP_HOT) { + int i; + + for (i = 0; i < THROTTLE_SIZE; i++) { + struct thermal_cooling_device *cdev; + struct soctherm_throt_cfg *stc; + + if (!ts->throt_cfgs[i].init) + continue; + + cdev = ts->throt_cfgs[i].cdev; + if (get_thermal_instance(tz, cdev, trip)) + stc = find_throttle_cfg_by_name(ts, cdev->type); + else + continue; + + return throttrip_program(dev, sg, stc, temp); + } + } + + return 0; +} + +static const struct thermal_zone_of_device_ops tegra_of_thermal_ops = { + .get_temp = tegra_thermctl_get_temp, + .set_trip_temp = tegra_thermctl_set_trip_temp, +}; + static int get_hot_temp(struct thermal_zone_device *tz, int *trip, int *temp) { int ntrips, i, ret; diff --git a/drivers/thermal/thermal_hwmon.c b/drivers/thermal/thermal_hwmon.c index 541af5946203..c4a508a124dc 100644 --- a/drivers/thermal/thermal_hwmon.c +++ b/drivers/thermal/thermal_hwmon.c @@ -59,14 +59,6 @@ static LIST_HEAD(thermal_hwmon_list); static DEFINE_MUTEX(thermal_hwmon_list_lock); static ssize_t -name_show(struct device *dev, struct device_attribute *attr, char *buf) -{ - struct thermal_hwmon_device *hwmon = dev_get_drvdata(dev); - return sprintf(buf, "%s\n", hwmon->type); -} -static DEVICE_ATTR_RO(name); - -static ssize_t temp_input_show(struct device *dev, struct device_attribute *attr, char *buf) { int temperature; @@ -165,15 +157,12 @@ int thermal_add_hwmon_sysfs(struct thermal_zone_device *tz) INIT_LIST_HEAD(&hwmon->tz_list); strlcpy(hwmon->type, tz->type, THERMAL_NAME_LENGTH); - hwmon->device = hwmon_device_register(NULL); + hwmon->device = hwmon_device_register_with_info(NULL, hwmon->type, + hwmon, NULL, NULL); if (IS_ERR(hwmon->device)) { result = PTR_ERR(hwmon->device); goto free_mem; } - dev_set_drvdata(hwmon->device, hwmon); - result = device_create_file(hwmon->device, &dev_attr_name); - if (result) - goto free_mem; register_sys_interface: temp = kzalloc(sizeof(*temp), GFP_KERNEL); @@ -222,10 +211,8 @@ int thermal_add_hwmon_sysfs(struct thermal_zone_device *tz) free_temp_mem: kfree(temp); unregister_name: - if (new_hwmon_device) { - device_remove_file(hwmon->device, &dev_attr_name); + if (new_hwmon_device) hwmon_device_unregister(hwmon->device); - } free_mem: if (new_hwmon_device) kfree(hwmon); @@ -267,7 +254,6 @@ void thermal_remove_hwmon_sysfs(struct thermal_zone_device *tz) list_del(&hwmon->node); mutex_unlock(&thermal_hwmon_list_lock); - device_remove_file(hwmon->device, &dev_attr_name); hwmon_device_unregister(hwmon->device); kfree(hwmon); } diff --git a/drivers/thermal/thermal_sysfs.c b/drivers/thermal/thermal_sysfs.c index fb80c96d8f73..ba81c9080f6e 100644 --- a/drivers/thermal/thermal_sysfs.c +++ b/drivers/thermal/thermal_sysfs.c @@ -317,7 +317,7 @@ emul_temp_store(struct device *dev, struct device_attribute *attr, return ret ? ret : count; } -static DEVICE_ATTR(emul_temp, S_IWUSR, NULL, emul_temp_store); +static DEVICE_ATTR_WO(emul_temp); #endif static ssize_t @@ -396,16 +396,15 @@ create_s32_tzp_attr(offset); * All the attributes created for tzp (create_s32_tzp_attr) also are always * present on the sysfs interface. */ -static DEVICE_ATTR(type, 0444, type_show, NULL); -static DEVICE_ATTR(temp, 0444, temp_show, NULL); -static DEVICE_ATTR(policy, S_IRUGO | S_IWUSR, policy_show, policy_store); -static DEVICE_ATTR(available_policies, S_IRUGO, available_policies_show, NULL); -static DEVICE_ATTR(sustainable_power, S_IWUSR | S_IRUGO, sustainable_power_show, - sustainable_power_store); +static DEVICE_ATTR_RO(type); +static DEVICE_ATTR_RO(temp); +static DEVICE_ATTR_RW(policy); +static DEVICE_ATTR_RO(available_policies); +static DEVICE_ATTR_RW(sustainable_power); /* These thermal zone device attributes are created based on conditions */ -static DEVICE_ATTR(mode, 0644, mode_show, mode_store); -static DEVICE_ATTR(passive, S_IRUGO | S_IWUSR, passive_show, passive_store); +static DEVICE_ATTR_RW(mode); +static DEVICE_ATTR_RW(passive); /* These attributes are unconditionally added to a thermal zone */ static struct attribute *thermal_zone_dev_attrs[] = { diff --git a/drivers/thermal/x86_pkg_temp_thermal.c b/drivers/thermal/x86_pkg_temp_thermal.c index d93eee2f101b..1a6c88b10a39 100644 --- a/drivers/thermal/x86_pkg_temp_thermal.c +++ b/drivers/thermal/x86_pkg_temp_thermal.c @@ -96,12 +96,12 @@ static int pkg_temp_debugfs_init(void) return -ENOENT; d = debugfs_create_u32("pkg_thres_interrupt", S_IRUGO, debugfs, - (u32 *)&pkg_interrupt_cnt); + &pkg_interrupt_cnt); if (!d) goto err_out; d = debugfs_create_u32("pkg_thres_work", S_IRUGO, debugfs, - (u32 *)&pkg_work_cnt); + &pkg_work_cnt); if (!d) goto err_out; |