Merge branch 'for-5.4' of git://git.kernel.org/pub/scm/linux/kernel/git/rzhang/linux
Pull thermal management updates from Zhang Rui: - Add Amit Kucheria as thermal subsystem Reviewer (Amit Kucheria) - Fix a use after free bug when unregistering thermal zone devices (Ido Schimmel) - Fix thermal core framework to use put_device() when device_register() fails (Yue Hu) - Enable intel_pch_thermal and MMIO RAPL support for Intel Icelake platform (Srinivas Pandruvada) - Add clock operations in qorip thermal driver, for some platforms with clock control like i.MX8MQ (Anson Huang) - A couple of trivial fixes and cleanups for thermal core and different soc thermal drivers (Amit Kucheria, Christophe JAILLET, Chuhong Yuan, Fuqian Huang, Kelsey Skunberg, Nathan Huckleberry, Rishi Gupta, Srinivas Kandagatla) * 'for-5.4' of git://git.kernel.org/pub/scm/linux/kernel/git/rzhang/linux: MAINTAINERS: Add Amit Kucheria as reviewer for thermal thermal: Add some error messages thermal: Fix use-after-free when unregistering thermal zone device thermal/drivers/core: Use put_device() if device_register() fails thermal_hwmon: Sanitize thermal_zone type thermal: intel: Use dev_get_drvdata thermal: intel: int3403: replace printk(KERN_WARN...) with pr_warn(...) thermal: intel: int340x_thermal: Remove unnecessary acpi_has_method() uses thermal: int340x: processor_thermal: Add Ice Lake support drivers: thermal: qcom: tsens: Fix memory leak from qfprom read thermal: tegra: Fix a typo thermal: rcar_gen3_thermal: Replace devm_add_action() followed by failure action with devm_add_action_or_reset() thermal: armada: Fix -Wshift-negative-value dt-bindings: thermal: qoriq: Add optional clocks property thermal: qoriq: Use __maybe_unused instead of #if CONFIG_PM_SLEEP thermal: qoriq: Use devm_platform_ioremap_resource() instead of of_iomap() thermal: qoriq: Fix error path of calling qoriq_tmu_register_tmu_zone fail thermal: qoriq: Add clock operations drivers: thermal: processor_thermal_device: Export sysfs interface for TCC offset
This commit is contained in:
commit
d0e00bc5ad
|
@ -23,6 +23,7 @@ Required properties:
|
||||||
Optional property:
|
Optional property:
|
||||||
- little-endian : If present, the TMU registers are little endian. If absent,
|
- little-endian : If present, the TMU registers are little endian. If absent,
|
||||||
the default is big endian.
|
the default is big endian.
|
||||||
|
- clocks : the clock for clocking the TMU silicon.
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
|
|
||||||
|
|
|
@ -16072,6 +16072,7 @@ THERMAL
|
||||||
M: Zhang Rui <rui.zhang@intel.com>
|
M: Zhang Rui <rui.zhang@intel.com>
|
||||||
M: Eduardo Valentin <edubezval@gmail.com>
|
M: Eduardo Valentin <edubezval@gmail.com>
|
||||||
R: Daniel Lezcano <daniel.lezcano@linaro.org>
|
R: Daniel Lezcano <daniel.lezcano@linaro.org>
|
||||||
|
R: Amit Kucheria <amit.kucheria@verdurent.com>
|
||||||
L: linux-pm@vger.kernel.org
|
L: linux-pm@vger.kernel.org
|
||||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/rzhang/linux.git
|
T: git git://git.kernel.org/pub/scm/linux/kernel/git/rzhang/linux.git
|
||||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/evalenti/linux-soc-thermal.git
|
T: git git://git.kernel.org/pub/scm/linux/kernel/git/evalenti/linux-soc-thermal.git
|
||||||
|
|
|
@ -53,7 +53,6 @@
|
||||||
#define CONTROL0_TSEN_MODE_EXTERNAL 0x2
|
#define CONTROL0_TSEN_MODE_EXTERNAL 0x2
|
||||||
#define CONTROL0_TSEN_MODE_MASK 0x3
|
#define CONTROL0_TSEN_MODE_MASK 0x3
|
||||||
|
|
||||||
#define CONTROL1_TSEN_AVG_SHIFT 0
|
|
||||||
#define CONTROL1_TSEN_AVG_MASK 0x7
|
#define CONTROL1_TSEN_AVG_MASK 0x7
|
||||||
#define CONTROL1_EXT_TSEN_SW_RESET BIT(7)
|
#define CONTROL1_EXT_TSEN_SW_RESET BIT(7)
|
||||||
#define CONTROL1_EXT_TSEN_HW_RESETn BIT(8)
|
#define CONTROL1_EXT_TSEN_HW_RESETn BIT(8)
|
||||||
|
@ -267,8 +266,8 @@ static void armada_cp110_init(struct platform_device *pdev,
|
||||||
|
|
||||||
/* Average the output value over 2^1 = 2 samples */
|
/* Average the output value over 2^1 = 2 samples */
|
||||||
regmap_read(priv->syscon, data->syscon_control1_off, ®);
|
regmap_read(priv->syscon, data->syscon_control1_off, ®);
|
||||||
reg &= ~CONTROL1_TSEN_AVG_MASK << CONTROL1_TSEN_AVG_SHIFT;
|
reg &= ~CONTROL1_TSEN_AVG_MASK;
|
||||||
reg |= 1 << CONTROL1_TSEN_AVG_SHIFT;
|
reg |= 1;
|
||||||
regmap_write(priv->syscon, data->syscon_control1_off, reg);
|
regmap_write(priv->syscon, data->syscon_control1_off, reg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -77,9 +77,6 @@ int acpi_parse_trt(acpi_handle handle, int *trt_count, struct trt **trtp,
|
||||||
struct acpi_buffer element = { 0, NULL };
|
struct acpi_buffer element = { 0, NULL };
|
||||||
struct acpi_buffer trt_format = { sizeof("RRNNNNNN"), "RRNNNNNN" };
|
struct acpi_buffer trt_format = { sizeof("RRNNNNNN"), "RRNNNNNN" };
|
||||||
|
|
||||||
if (!acpi_has_method(handle, "_TRT"))
|
|
||||||
return -ENODEV;
|
|
||||||
|
|
||||||
status = acpi_evaluate_object(handle, "_TRT", NULL, &buffer);
|
status = acpi_evaluate_object(handle, "_TRT", NULL, &buffer);
|
||||||
if (ACPI_FAILURE(status))
|
if (ACPI_FAILURE(status))
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
|
@ -158,9 +155,6 @@ int acpi_parse_art(acpi_handle handle, int *art_count, struct art **artp,
|
||||||
struct acpi_buffer art_format = {
|
struct acpi_buffer art_format = {
|
||||||
sizeof("RRNNNNNNNNNNN"), "RRNNNNNNNNNNN" };
|
sizeof("RRNNNNNNNNNNN"), "RRNNNNNNNNNNN" };
|
||||||
|
|
||||||
if (!acpi_has_method(handle, "_ART"))
|
|
||||||
return -ENODEV;
|
|
||||||
|
|
||||||
status = acpi_evaluate_object(handle, "_ART", NULL, &buffer);
|
status = acpi_evaluate_object(handle, "_ART", NULL, &buffer);
|
||||||
if (ACPI_FAILURE(status))
|
if (ACPI_FAILURE(status))
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
|
|
|
@ -181,7 +181,7 @@ static int int3403_cdev_add(struct int3403_priv *priv)
|
||||||
|
|
||||||
p = buf.pointer;
|
p = buf.pointer;
|
||||||
if (!p || (p->type != ACPI_TYPE_PACKAGE)) {
|
if (!p || (p->type != ACPI_TYPE_PACKAGE)) {
|
||||||
printk(KERN_WARNING "Invalid PPSS data\n");
|
pr_warn("Invalid PPSS data\n");
|
||||||
kfree(buf.pointer);
|
kfree(buf.pointer);
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,6 +39,9 @@
|
||||||
/* GeminiLake thermal reporting device */
|
/* GeminiLake thermal reporting device */
|
||||||
#define PCI_DEVICE_ID_PROC_GLK_THERMAL 0x318C
|
#define PCI_DEVICE_ID_PROC_GLK_THERMAL 0x318C
|
||||||
|
|
||||||
|
/* IceLake thermal reporting device */
|
||||||
|
#define PCI_DEVICE_ID_PROC_ICL_THERMAL 0x8a03
|
||||||
|
|
||||||
#define DRV_NAME "proc_thermal"
|
#define DRV_NAME "proc_thermal"
|
||||||
|
|
||||||
struct power_config {
|
struct power_config {
|
||||||
|
@ -137,6 +140,72 @@ static const struct attribute_group power_limit_attribute_group = {
|
||||||
.name = "power_limits"
|
.name = "power_limits"
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static ssize_t tcc_offset_degree_celsius_show(struct device *dev,
|
||||||
|
struct device_attribute *attr, char *buf)
|
||||||
|
{
|
||||||
|
u64 val;
|
||||||
|
int err;
|
||||||
|
|
||||||
|
err = rdmsrl_safe(MSR_IA32_TEMPERATURE_TARGET, &val);
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
|
|
||||||
|
val = (val >> 24) & 0xff;
|
||||||
|
return sprintf(buf, "%d\n", (int)val);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int tcc_offset_update(int tcc)
|
||||||
|
{
|
||||||
|
u64 val;
|
||||||
|
int err;
|
||||||
|
|
||||||
|
if (!tcc)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
err = rdmsrl_safe(MSR_IA32_TEMPERATURE_TARGET, &val);
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
|
|
||||||
|
val &= ~GENMASK_ULL(31, 24);
|
||||||
|
val |= (tcc & 0xff) << 24;
|
||||||
|
|
||||||
|
err = wrmsrl_safe(MSR_IA32_TEMPERATURE_TARGET, val);
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int tcc_offset_save;
|
||||||
|
|
||||||
|
static ssize_t tcc_offset_degree_celsius_store(struct device *dev,
|
||||||
|
struct device_attribute *attr, const char *buf,
|
||||||
|
size_t count)
|
||||||
|
{
|
||||||
|
u64 val;
|
||||||
|
int tcc, err;
|
||||||
|
|
||||||
|
err = rdmsrl_safe(MSR_PLATFORM_INFO, &val);
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
|
|
||||||
|
if (!(val & BIT(30)))
|
||||||
|
return -EACCES;
|
||||||
|
|
||||||
|
if (kstrtoint(buf, 0, &tcc))
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
err = tcc_offset_update(tcc);
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
|
|
||||||
|
tcc_offset_save = tcc;
|
||||||
|
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
static DEVICE_ATTR_RW(tcc_offset_degree_celsius);
|
||||||
|
|
||||||
static int stored_tjmax; /* since it is fixed, we can have local storage */
|
static int stored_tjmax; /* since it is fixed, we can have local storage */
|
||||||
|
|
||||||
static int get_tjmax(void)
|
static int get_tjmax(void)
|
||||||
|
@ -332,6 +401,7 @@ static void proc_thermal_remove(struct proc_thermal_device *proc_priv)
|
||||||
acpi_remove_notify_handler(proc_priv->adev->handle,
|
acpi_remove_notify_handler(proc_priv->adev->handle,
|
||||||
ACPI_DEVICE_NOTIFY, proc_thermal_notify);
|
ACPI_DEVICE_NOTIFY, proc_thermal_notify);
|
||||||
int340x_thermal_zone_remove(proc_priv->int340x_zone);
|
int340x_thermal_zone_remove(proc_priv->int340x_zone);
|
||||||
|
sysfs_remove_file(&proc_priv->dev->kobj, &dev_attr_tcc_offset_degree_celsius.attr);
|
||||||
sysfs_remove_group(&proc_priv->dev->kobj,
|
sysfs_remove_group(&proc_priv->dev->kobj,
|
||||||
&power_limit_attribute_group);
|
&power_limit_attribute_group);
|
||||||
}
|
}
|
||||||
|
@ -355,8 +425,15 @@ static int int3401_add(struct platform_device *pdev)
|
||||||
|
|
||||||
dev_info(&pdev->dev, "Creating sysfs group for PROC_THERMAL_PLATFORM_DEV\n");
|
dev_info(&pdev->dev, "Creating sysfs group for PROC_THERMAL_PLATFORM_DEV\n");
|
||||||
|
|
||||||
return sysfs_create_group(&pdev->dev.kobj,
|
ret = sysfs_create_file(&pdev->dev.kobj, &dev_attr_tcc_offset_degree_celsius.attr);
|
||||||
&power_limit_attribute_group);
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
ret = sysfs_create_group(&pdev->dev.kobj, &power_limit_attribute_group);
|
||||||
|
if (ret)
|
||||||
|
sysfs_remove_file(&pdev->dev.kobj, &dev_attr_tcc_offset_degree_celsius.attr);
|
||||||
|
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int int3401_remove(struct platform_device *pdev)
|
static int int3401_remove(struct platform_device *pdev)
|
||||||
|
@ -588,8 +665,15 @@ static int proc_thermal_pci_probe(struct pci_dev *pdev,
|
||||||
|
|
||||||
dev_info(&pdev->dev, "Creating sysfs group for PROC_THERMAL_PCI\n");
|
dev_info(&pdev->dev, "Creating sysfs group for PROC_THERMAL_PCI\n");
|
||||||
|
|
||||||
return sysfs_create_group(&pdev->dev.kobj,
|
ret = sysfs_create_file(&pdev->dev.kobj, &dev_attr_tcc_offset_degree_celsius.attr);
|
||||||
&power_limit_attribute_group);
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
ret = sysfs_create_group(&pdev->dev.kobj, &power_limit_attribute_group);
|
||||||
|
if (ret)
|
||||||
|
sysfs_remove_file(&pdev->dev.kobj, &dev_attr_tcc_offset_degree_celsius.attr);
|
||||||
|
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void proc_thermal_pci_remove(struct pci_dev *pdev)
|
static void proc_thermal_pci_remove(struct pci_dev *pdev)
|
||||||
|
@ -615,6 +699,8 @@ static int proc_thermal_resume(struct device *dev)
|
||||||
proc_dev = dev_get_drvdata(dev);
|
proc_dev = dev_get_drvdata(dev);
|
||||||
proc_thermal_read_ppcc(proc_dev);
|
proc_thermal_read_ppcc(proc_dev);
|
||||||
|
|
||||||
|
tcc_offset_update(tcc_offset_save);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
|
@ -636,6 +722,8 @@ static const struct pci_device_id proc_thermal_pci_ids[] = {
|
||||||
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_PROC_CNL_THERMAL)},
|
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_PROC_CNL_THERMAL)},
|
||||||
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_PROC_CFL_THERMAL)},
|
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_PROC_CFL_THERMAL)},
|
||||||
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_PROC_GLK_THERMAL)},
|
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_PROC_GLK_THERMAL)},
|
||||||
|
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_PROC_ICL_THERMAL),
|
||||||
|
.driver_data = (kernel_ulong_t)&rapl_mmio_hsw, },
|
||||||
{ 0, },
|
{ 0, },
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -371,16 +371,14 @@ static void intel_pch_thermal_remove(struct pci_dev *pdev)
|
||||||
|
|
||||||
static int intel_pch_thermal_suspend(struct device *device)
|
static int intel_pch_thermal_suspend(struct device *device)
|
||||||
{
|
{
|
||||||
struct pci_dev *pdev = to_pci_dev(device);
|
struct pch_thermal_device *ptd = dev_get_drvdata(device);
|
||||||
struct pch_thermal_device *ptd = pci_get_drvdata(pdev);
|
|
||||||
|
|
||||||
return ptd->ops->suspend(ptd);
|
return ptd->ops->suspend(ptd);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int intel_pch_thermal_resume(struct device *device)
|
static int intel_pch_thermal_resume(struct device *device)
|
||||||
{
|
{
|
||||||
struct pci_dev *pdev = to_pci_dev(device);
|
struct pch_thermal_device *ptd = dev_get_drvdata(device);
|
||||||
struct pch_thermal_device *ptd = pci_get_drvdata(pdev);
|
|
||||||
|
|
||||||
return ptd->ops->resume(ptd);
|
return ptd->ops->resume(ptd);
|
||||||
}
|
}
|
||||||
|
|
|
@ -229,6 +229,8 @@ static int calibrate_8960(struct tsens_priv *priv)
|
||||||
for (i = 0; i < num_read; i++, s++)
|
for (i = 0; i < num_read; i++, s++)
|
||||||
s->offset = data[i];
|
s->offset = data[i];
|
||||||
|
|
||||||
|
kfree(data);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -145,8 +145,10 @@ static int calibrate_8916(struct tsens_priv *priv)
|
||||||
return PTR_ERR(qfprom_cdata);
|
return PTR_ERR(qfprom_cdata);
|
||||||
|
|
||||||
qfprom_csel = (u32 *)qfprom_read(priv->dev, "calib_sel");
|
qfprom_csel = (u32 *)qfprom_read(priv->dev, "calib_sel");
|
||||||
if (IS_ERR(qfprom_csel))
|
if (IS_ERR(qfprom_csel)) {
|
||||||
|
kfree(qfprom_cdata);
|
||||||
return PTR_ERR(qfprom_csel);
|
return PTR_ERR(qfprom_csel);
|
||||||
|
}
|
||||||
|
|
||||||
mode = (qfprom_csel[0] & MSM8916_CAL_SEL_MASK) >> MSM8916_CAL_SEL_SHIFT;
|
mode = (qfprom_csel[0] & MSM8916_CAL_SEL_MASK) >> MSM8916_CAL_SEL_SHIFT;
|
||||||
dev_dbg(priv->dev, "calibration mode is %d\n", mode);
|
dev_dbg(priv->dev, "calibration mode is %d\n", mode);
|
||||||
|
@ -181,6 +183,8 @@ static int calibrate_8916(struct tsens_priv *priv)
|
||||||
}
|
}
|
||||||
|
|
||||||
compute_intercept_slope(priv, p1, p2, mode);
|
compute_intercept_slope(priv, p1, p2, mode);
|
||||||
|
kfree(qfprom_cdata);
|
||||||
|
kfree(qfprom_csel);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -198,8 +202,10 @@ static int calibrate_8974(struct tsens_priv *priv)
|
||||||
return PTR_ERR(calib);
|
return PTR_ERR(calib);
|
||||||
|
|
||||||
bkp = (u32 *)qfprom_read(priv->dev, "calib_backup");
|
bkp = (u32 *)qfprom_read(priv->dev, "calib_backup");
|
||||||
if (IS_ERR(bkp))
|
if (IS_ERR(bkp)) {
|
||||||
|
kfree(calib);
|
||||||
return PTR_ERR(bkp);
|
return PTR_ERR(bkp);
|
||||||
|
}
|
||||||
|
|
||||||
calib_redun_sel = bkp[1] & BKP_REDUN_SEL;
|
calib_redun_sel = bkp[1] & BKP_REDUN_SEL;
|
||||||
calib_redun_sel >>= BKP_REDUN_SHIFT;
|
calib_redun_sel >>= BKP_REDUN_SHIFT;
|
||||||
|
@ -313,6 +319,8 @@ static int calibrate_8974(struct tsens_priv *priv)
|
||||||
}
|
}
|
||||||
|
|
||||||
compute_intercept_slope(priv, p1, p2, mode);
|
compute_intercept_slope(priv, p1, p2, mode);
|
||||||
|
kfree(calib);
|
||||||
|
kfree(bkp);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -138,6 +138,7 @@ static int calibrate_v1(struct tsens_priv *priv)
|
||||||
}
|
}
|
||||||
|
|
||||||
compute_intercept_slope(priv, p1, p2, mode);
|
compute_intercept_slope(priv, p1, p2, mode);
|
||||||
|
kfree(qfprom_cdata);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
|
|
||||||
#include <linux/thermal.h>
|
#include <linux/thermal.h>
|
||||||
#include <linux/regmap.h>
|
#include <linux/regmap.h>
|
||||||
|
#include <linux/slab.h>
|
||||||
|
|
||||||
struct tsens_priv;
|
struct tsens_priv;
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
//
|
//
|
||||||
// Copyright 2016 Freescale Semiconductor, Inc.
|
// Copyright 2016 Freescale Semiconductor, Inc.
|
||||||
|
|
||||||
|
#include <linux/clk.h>
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/platform_device.h>
|
#include <linux/platform_device.h>
|
||||||
#include <linux/err.h>
|
#include <linux/err.h>
|
||||||
|
@ -72,6 +73,7 @@ struct qoriq_sensor {
|
||||||
|
|
||||||
struct qoriq_tmu_data {
|
struct qoriq_tmu_data {
|
||||||
struct qoriq_tmu_regs __iomem *regs;
|
struct qoriq_tmu_regs __iomem *regs;
|
||||||
|
struct clk *clk;
|
||||||
bool little_endian;
|
bool little_endian;
|
||||||
struct qoriq_sensor *sensor[SITES_MAX];
|
struct qoriq_sensor *sensor[SITES_MAX];
|
||||||
};
|
};
|
||||||
|
@ -202,32 +204,39 @@ static int qoriq_tmu_probe(struct platform_device *pdev)
|
||||||
|
|
||||||
data->little_endian = of_property_read_bool(np, "little-endian");
|
data->little_endian = of_property_read_bool(np, "little-endian");
|
||||||
|
|
||||||
data->regs = of_iomap(np, 0);
|
data->regs = devm_platform_ioremap_resource(pdev, 0);
|
||||||
if (!data->regs) {
|
if (IS_ERR(data->regs)) {
|
||||||
dev_err(&pdev->dev, "Failed to get memory region\n");
|
dev_err(&pdev->dev, "Failed to get memory region\n");
|
||||||
ret = -ENODEV;
|
return PTR_ERR(data->regs);
|
||||||
goto err_iomap;
|
}
|
||||||
|
|
||||||
|
data->clk = devm_clk_get_optional(&pdev->dev, NULL);
|
||||||
|
if (IS_ERR(data->clk))
|
||||||
|
return PTR_ERR(data->clk);
|
||||||
|
|
||||||
|
ret = clk_prepare_enable(data->clk);
|
||||||
|
if (ret) {
|
||||||
|
dev_err(&pdev->dev, "Failed to enable clock\n");
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
qoriq_tmu_init_device(data); /* TMU initialization */
|
qoriq_tmu_init_device(data); /* TMU initialization */
|
||||||
|
|
||||||
ret = qoriq_tmu_calibration(pdev); /* TMU calibration */
|
ret = qoriq_tmu_calibration(pdev); /* TMU calibration */
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
goto err_tmu;
|
goto err;
|
||||||
|
|
||||||
ret = qoriq_tmu_register_tmu_zone(pdev);
|
ret = qoriq_tmu_register_tmu_zone(pdev);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
dev_err(&pdev->dev, "Failed to register sensors\n");
|
dev_err(&pdev->dev, "Failed to register sensors\n");
|
||||||
ret = -ENODEV;
|
ret = -ENODEV;
|
||||||
goto err_iomap;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
err_tmu:
|
err:
|
||||||
iounmap(data->regs);
|
clk_disable_unprepare(data->clk);
|
||||||
|
|
||||||
err_iomap:
|
|
||||||
platform_set_drvdata(pdev, NULL);
|
platform_set_drvdata(pdev, NULL);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -240,14 +249,14 @@ static int qoriq_tmu_remove(struct platform_device *pdev)
|
||||||
/* Disable monitoring */
|
/* Disable monitoring */
|
||||||
tmu_write(data, TMR_DISABLE, &data->regs->tmr);
|
tmu_write(data, TMR_DISABLE, &data->regs->tmr);
|
||||||
|
|
||||||
iounmap(data->regs);
|
clk_disable_unprepare(data->clk);
|
||||||
|
|
||||||
platform_set_drvdata(pdev, NULL);
|
platform_set_drvdata(pdev, NULL);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_PM_SLEEP
|
static int __maybe_unused qoriq_tmu_suspend(struct device *dev)
|
||||||
static int qoriq_tmu_suspend(struct device *dev)
|
|
||||||
{
|
{
|
||||||
u32 tmr;
|
u32 tmr;
|
||||||
struct qoriq_tmu_data *data = dev_get_drvdata(dev);
|
struct qoriq_tmu_data *data = dev_get_drvdata(dev);
|
||||||
|
@ -257,14 +266,21 @@ static int qoriq_tmu_suspend(struct device *dev)
|
||||||
tmr &= ~TMR_ME;
|
tmr &= ~TMR_ME;
|
||||||
tmu_write(data, tmr, &data->regs->tmr);
|
tmu_write(data, tmr, &data->regs->tmr);
|
||||||
|
|
||||||
|
clk_disable_unprepare(data->clk);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int qoriq_tmu_resume(struct device *dev)
|
static int __maybe_unused qoriq_tmu_resume(struct device *dev)
|
||||||
{
|
{
|
||||||
u32 tmr;
|
u32 tmr;
|
||||||
|
int ret;
|
||||||
struct qoriq_tmu_data *data = dev_get_drvdata(dev);
|
struct qoriq_tmu_data *data = dev_get_drvdata(dev);
|
||||||
|
|
||||||
|
ret = clk_prepare_enable(data->clk);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
/* Enable monitoring */
|
/* Enable monitoring */
|
||||||
tmr = tmu_read(data, &data->regs->tmr);
|
tmr = tmu_read(data, &data->regs->tmr);
|
||||||
tmr |= TMR_ME;
|
tmr |= TMR_ME;
|
||||||
|
@ -272,7 +288,6 @@ static int qoriq_tmu_resume(struct device *dev)
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
static SIMPLE_DEV_PM_OPS(qoriq_tmu_pm_ops,
|
static SIMPLE_DEV_PM_OPS(qoriq_tmu_pm_ops,
|
||||||
qoriq_tmu_suspend, qoriq_tmu_resume);
|
qoriq_tmu_suspend, qoriq_tmu_resume);
|
||||||
|
|
|
@ -443,9 +443,8 @@ static int rcar_gen3_thermal_probe(struct platform_device *pdev)
|
||||||
if (ret)
|
if (ret)
|
||||||
goto error_unregister;
|
goto error_unregister;
|
||||||
|
|
||||||
ret = devm_add_action(dev, rcar_gen3_hwmon_action, zone);
|
ret = devm_add_action_or_reset(dev, rcar_gen3_hwmon_action, zone);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
rcar_gen3_hwmon_action(zone);
|
|
||||||
goto error_unregister;
|
goto error_unregister;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -202,7 +202,7 @@
|
||||||
/* get dividend from the depth */
|
/* get dividend from the depth */
|
||||||
#define THROT_DEPTH_DIVIDEND(depth) ((256 * (100 - (depth)) / 100) - 1)
|
#define THROT_DEPTH_DIVIDEND(depth) ((256 * (100 - (depth)) / 100) - 1)
|
||||||
|
|
||||||
/* gk20a nv_therm interface N:3 Mapping. Levels defined in tegra124-sochterm.h
|
/* gk20a nv_therm interface N:3 Mapping. Levels defined in tegra124-soctherm.h
|
||||||
* level vector
|
* level vector
|
||||||
* NONE 3'b000
|
* NONE 3'b000
|
||||||
* LOW 3'b001
|
* LOW 3'b001
|
||||||
|
|
|
@ -304,7 +304,7 @@ static void thermal_zone_device_set_polling(struct thermal_zone_device *tz,
|
||||||
&tz->poll_queue,
|
&tz->poll_queue,
|
||||||
msecs_to_jiffies(delay));
|
msecs_to_jiffies(delay));
|
||||||
else
|
else
|
||||||
cancel_delayed_work(&tz->poll_queue);
|
cancel_delayed_work_sync(&tz->poll_queue);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void monitor_thermal_zone(struct thermal_zone_device *tz)
|
static void monitor_thermal_zone(struct thermal_zone_device *tz)
|
||||||
|
@ -985,7 +985,7 @@ __thermal_cooling_device_register(struct device_node *np,
|
||||||
result = device_register(&cdev->device);
|
result = device_register(&cdev->device);
|
||||||
if (result) {
|
if (result) {
|
||||||
ida_simple_remove(&thermal_cdev_ida, cdev->id);
|
ida_simple_remove(&thermal_cdev_ida, cdev->id);
|
||||||
kfree(cdev);
|
put_device(&cdev->device);
|
||||||
return ERR_PTR(result);
|
return ERR_PTR(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1240,21 +1240,31 @@ thermal_zone_device_register(const char *type, int trips, int mask,
|
||||||
struct thermal_zone_device *tz;
|
struct thermal_zone_device *tz;
|
||||||
enum thermal_trip_type trip_type;
|
enum thermal_trip_type trip_type;
|
||||||
int trip_temp;
|
int trip_temp;
|
||||||
|
int id;
|
||||||
int result;
|
int result;
|
||||||
int count;
|
int count;
|
||||||
struct thermal_governor *governor;
|
struct thermal_governor *governor;
|
||||||
|
|
||||||
if (!type || strlen(type) == 0)
|
if (!type || strlen(type) == 0) {
|
||||||
|
pr_err("Error: No thermal zone type defined\n");
|
||||||
return ERR_PTR(-EINVAL);
|
return ERR_PTR(-EINVAL);
|
||||||
|
}
|
||||||
|
|
||||||
if (type && strlen(type) >= THERMAL_NAME_LENGTH)
|
if (type && strlen(type) >= THERMAL_NAME_LENGTH) {
|
||||||
|
pr_err("Error: Thermal zone name (%s) too long, should be under %d chars\n",
|
||||||
|
type, THERMAL_NAME_LENGTH);
|
||||||
return ERR_PTR(-EINVAL);
|
return ERR_PTR(-EINVAL);
|
||||||
|
}
|
||||||
|
|
||||||
if (trips > THERMAL_MAX_TRIPS || trips < 0 || mask >> trips)
|
if (trips > THERMAL_MAX_TRIPS || trips < 0 || mask >> trips) {
|
||||||
|
pr_err("Error: Incorrect number of thermal trips\n");
|
||||||
return ERR_PTR(-EINVAL);
|
return ERR_PTR(-EINVAL);
|
||||||
|
}
|
||||||
|
|
||||||
if (!ops)
|
if (!ops) {
|
||||||
|
pr_err("Error: Thermal zone device ops not defined\n");
|
||||||
return ERR_PTR(-EINVAL);
|
return ERR_PTR(-EINVAL);
|
||||||
|
}
|
||||||
|
|
||||||
if (trips > 0 && (!ops->get_trip_type || !ops->get_trip_temp))
|
if (trips > 0 && (!ops->get_trip_type || !ops->get_trip_temp))
|
||||||
return ERR_PTR(-EINVAL);
|
return ERR_PTR(-EINVAL);
|
||||||
|
@ -1266,11 +1276,13 @@ thermal_zone_device_register(const char *type, int trips, int mask,
|
||||||
INIT_LIST_HEAD(&tz->thermal_instances);
|
INIT_LIST_HEAD(&tz->thermal_instances);
|
||||||
ida_init(&tz->ida);
|
ida_init(&tz->ida);
|
||||||
mutex_init(&tz->lock);
|
mutex_init(&tz->lock);
|
||||||
result = ida_simple_get(&thermal_tz_ida, 0, 0, GFP_KERNEL);
|
id = ida_simple_get(&thermal_tz_ida, 0, 0, GFP_KERNEL);
|
||||||
if (result < 0)
|
if (id < 0) {
|
||||||
|
result = id;
|
||||||
goto free_tz;
|
goto free_tz;
|
||||||
|
}
|
||||||
|
|
||||||
tz->id = result;
|
tz->id = id;
|
||||||
strlcpy(tz->type, type, sizeof(tz->type));
|
strlcpy(tz->type, type, sizeof(tz->type));
|
||||||
tz->ops = ops;
|
tz->ops = ops;
|
||||||
tz->tzp = tzp;
|
tz->tzp = tzp;
|
||||||
|
@ -1292,7 +1304,7 @@ thermal_zone_device_register(const char *type, int trips, int mask,
|
||||||
dev_set_name(&tz->device, "thermal_zone%d", tz->id);
|
dev_set_name(&tz->device, "thermal_zone%d", tz->id);
|
||||||
result = device_register(&tz->device);
|
result = device_register(&tz->device);
|
||||||
if (result)
|
if (result)
|
||||||
goto remove_device_groups;
|
goto release_device;
|
||||||
|
|
||||||
for (count = 0; count < trips; count++) {
|
for (count = 0; count < trips; count++) {
|
||||||
if (tz->ops->get_trip_type(tz, count, &trip_type))
|
if (tz->ops->get_trip_type(tz, count, &trip_type))
|
||||||
|
@ -1343,14 +1355,12 @@ thermal_zone_device_register(const char *type, int trips, int mask,
|
||||||
return tz;
|
return tz;
|
||||||
|
|
||||||
unregister:
|
unregister:
|
||||||
ida_simple_remove(&thermal_tz_ida, tz->id);
|
device_del(&tz->device);
|
||||||
device_unregister(&tz->device);
|
release_device:
|
||||||
return ERR_PTR(result);
|
put_device(&tz->device);
|
||||||
|
tz = NULL;
|
||||||
remove_device_groups:
|
|
||||||
thermal_zone_destroy_device_groups(tz);
|
|
||||||
remove_id:
|
remove_id:
|
||||||
ida_simple_remove(&thermal_tz_ida, tz->id);
|
ida_simple_remove(&thermal_tz_ida, id);
|
||||||
free_tz:
|
free_tz:
|
||||||
kfree(tz);
|
kfree(tz);
|
||||||
return ERR_PTR(result);
|
return ERR_PTR(result);
|
||||||
|
|
|
@ -87,13 +87,17 @@ static struct thermal_hwmon_device *
|
||||||
thermal_hwmon_lookup_by_type(const struct thermal_zone_device *tz)
|
thermal_hwmon_lookup_by_type(const struct thermal_zone_device *tz)
|
||||||
{
|
{
|
||||||
struct thermal_hwmon_device *hwmon;
|
struct thermal_hwmon_device *hwmon;
|
||||||
|
char type[THERMAL_NAME_LENGTH];
|
||||||
|
|
||||||
mutex_lock(&thermal_hwmon_list_lock);
|
mutex_lock(&thermal_hwmon_list_lock);
|
||||||
list_for_each_entry(hwmon, &thermal_hwmon_list, node)
|
list_for_each_entry(hwmon, &thermal_hwmon_list, node) {
|
||||||
if (!strcmp(hwmon->type, tz->type)) {
|
strcpy(type, tz->type);
|
||||||
|
strreplace(type, '-', '_');
|
||||||
|
if (!strcmp(hwmon->type, type)) {
|
||||||
mutex_unlock(&thermal_hwmon_list_lock);
|
mutex_unlock(&thermal_hwmon_list_lock);
|
||||||
return hwmon;
|
return hwmon;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
mutex_unlock(&thermal_hwmon_list_lock);
|
mutex_unlock(&thermal_hwmon_list_lock);
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
Loading…
Reference in New Issue