- Constify a variable in thermal mmio driver (Rikard Falkeborn)
- Add the current temperature in the netlink message when crossing a trip point in order to prevent useless back and forth reading from userspace (Daniel Lezcano) - Add support for the 'HC' variant on PM8998 pmic in order to support vadc channels on recent QCom boards (Bjorn Andersson) - Add support of calibration values from hardware when they are fused (Niklas Söderlund) - Fix NULL pointer dereference from the thermal_release callback when an error occured in the thermal_zone_device_register() function (Yuanzheng Song) - Fix use after free call in the __thermal_cooling_device_register() function in the error path (Ziyang Xuan) - Fix compilation error for the LMh driver when CONFIG_QCOM_SCM is not set (Jackie Liu) - Add a timeout when reading a register which can block forever under certain circumstances in the tsens driver (Ansuel Smith) - Add DT binding for the reset lines and use them in the rockchip sensor driver (Johan Jonker) - Add new uniphier NX1 SoC temperature sensor (Kunihiko Hayashi) - Save and restore the TCC value in the int340x driver (Antoine Tenart) - Deprecate the cooling device state sysfs file writable and the user space governor (Daniel Lezcano) -----BEGIN PGP SIGNATURE----- iQEzBAABCAAdFiEEGn3N4YVz0WNVyHskqDIjiipP6E8FAmFyyiYACgkQqDIjiipP 6E9dtwf+NCwF9QAD1iYyxA2A7ypqypmDtGxjKtNLsRDHOVsaQ1LurPb2RKArNWrB eth4/MooV37vqAHo0lA1uTP5SpWOLc05YLSccWf79nOlpCau8FRBrSGzPcSYAOBe ipjgbooxSrkERfnWX/MtyD8pnRRj6GfAo49WXx8bMoQ4HkxDTTqVbviqwkRJzZ69 Cokt65x2AqS0sBh1CsaGyp3LC+NgI7pbrVW0mLQvoCpLQo67bVHIcW9To5bIukp/ JiBpV+g46LAbcspR3BoWRUP/yVbMEUDd81ypyrXHOSXrxLec/7Oe6/sM/U7cVj5w 2+wBqo2K27gGFxy4X9BifFdqS2q3Tg== =cKM4 -----END PGP SIGNATURE----- Merge tag 'thermal-v5.16-rc1' of ssh://gitolite.kernel.org/pub/scm/linux/kernel/git/thermal/linux Pull thermal core and ARM thermal driver updates for v5.16 from Daniel Lezcano: - Constify a variable in thermal mmio driver (Rikard Falkeborn) - Add the current temperature in the netlink message when crossing a trip point in order to prevent useless back and forth reading from userspace (Daniel Lezcano) - Add support for the 'HC' variant on PM8998 pmic in order to support vadc channels on recent QCom boards (Bjorn Andersson) - Add support of calibration values from hardware when they are fused (Niklas Söderlund) - Fix NULL pointer dereference from the thermal_release callback when an error occured in the thermal_zone_device_register() function (Yuanzheng Song) - Fix use after free call in the __thermal_cooling_device_register() function in the error path (Ziyang Xuan) - Fix compilation error for the LMh driver when CONFIG_QCOM_SCM is not set (Jackie Liu) - Add a timeout when reading a register which can block forever under certain circumstances in the tsens driver (Ansuel Smith) - Add DT binding for the reset lines and use them in the rockchip sensor driver (Johan Jonker) - Add new uniphier NX1 SoC temperature sensor (Kunihiko Hayashi) - Save and restore the TCC value in the int340x driver (Antoine Tenart) - Deprecate the cooling device state sysfs file writable and the user space governor (Daniel Lezcano) * tag 'thermal-v5.16-rc1' of ssh://gitolite.kernel.org/pub/scm/linux/kernel/git/thermal/linux: thermal/core: Deprecate changing cooling device state from userspace thermal/core: Make the userspace governor deprecated thermal/drivers/int340x: Improve the tcc offset saving for suspend/resume thermal/drivers/uniphier: Add compatible string for NX1 SoC dt-bindings: thermal: uniphier: Add binding for NX1 SoC thermal/drivers/rockchip_thermal: Allow more resets for tsadc node dt-bindings: thermal: remove redundant comments from rockchip-thermal.yaml dt-bindings: thermal: allow more resets for tsadc node in rockchip-thermal.yaml thermal/drivers/tsens: Add timeout to get_temp_tsens_valid thermal/drivers/qcom/lmh: make QCOM_LMH depends on QCOM_SCM thermal/core: fix a UAF bug in __thermal_cooling_device_register() thermal/core: Fix null pointer dereference in thermal_release() thermal: rcar_gen3_thermal: Read calibration from hardware thermal: rcar_gen3_thermal: Store thcode and ptat in priv data thermal/drivers/qcom/spmi-adc-tm5: Add support for HC variant dt-bindings: thermal: qcom: add HC variant of adc-thermal monitor bindings thermal/drivers/netlink: Add the temperature when crossing a trip point thermal/drivers/thermal_mmio: Constify static struct thermal_mmio_ops
This commit is contained in:
Коммит
83e8de89b9
|
@ -0,0 +1,149 @@
|
|||
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/thermal/qcom-spmi-adc-tm-hc.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Qualcomm's SPMI PMIC ADC HC Thermal Monitoring
|
||||
maintainers:
|
||||
- Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: qcom,spmi-adc-tm-hc
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
interrupts:
|
||||
maxItems: 1
|
||||
|
||||
"#thermal-sensor-cells":
|
||||
const: 1
|
||||
description:
|
||||
Number of cells required to uniquely identify the thermal sensors. Since
|
||||
we have multiple sensors this is set to 1
|
||||
|
||||
"#address-cells":
|
||||
const: 1
|
||||
|
||||
"#size-cells":
|
||||
const: 0
|
||||
|
||||
qcom,avg-samples:
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
description: Number of samples to be used for measurement.
|
||||
enum:
|
||||
- 1
|
||||
- 2
|
||||
- 4
|
||||
- 8
|
||||
- 16
|
||||
default: 1
|
||||
|
||||
qcom,decimation:
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
description: This parameter is used to decrease ADC sampling rate.
|
||||
Quicker measurements can be made by reducing decimation ratio.
|
||||
enum:
|
||||
- 256
|
||||
- 512
|
||||
- 1024
|
||||
default: 1024
|
||||
|
||||
patternProperties:
|
||||
"^([-a-z0-9]*)@[0-7]$":
|
||||
type: object
|
||||
description:
|
||||
Represent one thermal sensor.
|
||||
|
||||
properties:
|
||||
reg:
|
||||
description: Specify the sensor channel. There are 8 channels in PMIC5's ADC TM
|
||||
minimum: 0
|
||||
maximum: 7
|
||||
|
||||
io-channels:
|
||||
description:
|
||||
From common IIO binding. Used to pipe PMIC ADC channel to thermal monitor
|
||||
|
||||
qcom,ratiometric:
|
||||
$ref: /schemas/types.yaml#/definitions/flag
|
||||
description:
|
||||
Channel calibration type.
|
||||
If this property is specified VADC will use the VDD reference
|
||||
(1.875V) and GND for channel calibration. If property is not found,
|
||||
channel will be calibrated with 0V and 1.25V reference channels,
|
||||
also known as absolute calibration.
|
||||
|
||||
qcom,hw-settle-time-us:
|
||||
description: Time between AMUX getting configured and the ADC starting conversion.
|
||||
enum: [0, 100, 200, 300, 400, 500, 600, 700, 1000, 2000, 4000, 6000, 8000, 10000]
|
||||
|
||||
qcom,pre-scaling:
|
||||
$ref: /schemas/types.yaml#/definitions/uint32-array
|
||||
description: Used for scaling the channel input signal before the
|
||||
signal is fed to VADC. The configuration for this node is to know the
|
||||
pre-determined ratio and use it for post scaling. It is a pair of
|
||||
integers, denoting the numerator and denominator of the fraction by
|
||||
which input signal is multiplied. For example, <1 3> indicates the
|
||||
signal is scaled down to 1/3 of its value before ADC measurement. If
|
||||
property is not found default value depending on chip will be used.
|
||||
items:
|
||||
- const: 1
|
||||
- enum: [ 1, 3, 4, 6, 20, 8, 10 ]
|
||||
|
||||
required:
|
||||
- reg
|
||||
- io-channels
|
||||
|
||||
additionalProperties:
|
||||
false
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- interrupts
|
||||
- "#address-cells"
|
||||
- "#size-cells"
|
||||
- "#thermal-sensor-cells"
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/iio/qcom,spmi-vadc.h>
|
||||
#include <dt-bindings/interrupt-controller/irq.h>
|
||||
spmi_bus {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
pm8998_adc: adc@3100 {
|
||||
reg = <0x3100>;
|
||||
compatible = "qcom,spmi-adc-rev2";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
#io-channel-cells = <1>;
|
||||
|
||||
/* Other propreties are omitted */
|
||||
adc-chan@4c {
|
||||
reg = <ADC5_XO_THERM_100K_PU>;
|
||||
};
|
||||
};
|
||||
|
||||
pm8998_adc_tm: adc-tm@3400 {
|
||||
compatible = "qcom,spmi-adc-tm-hc";
|
||||
reg = <0x3400>;
|
||||
interrupts = <0x2 0x34 0x0 IRQ_TYPE_EDGE_RISING>;
|
||||
#thermal-sensor-cells = <1>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
thermistor@1 {
|
||||
reg = <1>;
|
||||
io-channels = <&pm8998_adc ADC5_XO_THERM_100K_PU>;
|
||||
qcom,ratiometric;
|
||||
qcom,hw-settle-time-us = <200>;
|
||||
};
|
||||
};
|
||||
};
|
||||
...
|
|
@ -12,14 +12,14 @@ maintainers:
|
|||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- rockchip,px30-tsadc # PX30 SoCs
|
||||
- rockchip,rv1108-tsadc # RV1108 SoCs
|
||||
- rockchip,rk3228-tsadc # RK3228 SoCs
|
||||
- rockchip,rk3288-tsadc # RK3288 SoCs
|
||||
- rockchip,rk3328-tsadc # RK3328 SoCs
|
||||
- rockchip,rk3368-tsadc # RK3368 SoCs
|
||||
- rockchip,rk3399-tsadc # RK3399 SoCs
|
||||
- rockchip,rk3568-tsadc # RK3568 SoCs
|
||||
- rockchip,px30-tsadc
|
||||
- rockchip,rk3228-tsadc
|
||||
- rockchip,rk3288-tsadc
|
||||
- rockchip,rk3328-tsadc
|
||||
- rockchip,rk3368-tsadc
|
||||
- rockchip,rk3399-tsadc
|
||||
- rockchip,rk3568-tsadc
|
||||
- rockchip,rv1108-tsadc
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
@ -37,11 +37,15 @@ properties:
|
|||
- const: apb_pclk
|
||||
|
||||
resets:
|
||||
maxItems: 1
|
||||
minItems: 1
|
||||
maxItems: 3
|
||||
|
||||
reset-names:
|
||||
minItems: 1
|
||||
items:
|
||||
- const: tsadc-apb
|
||||
- const: tsadc
|
||||
- const: tsadc-phy
|
||||
|
||||
"#thermal-sensor-cells":
|
||||
const: 1
|
||||
|
@ -71,7 +75,6 @@ required:
|
|||
- clocks
|
||||
- clock-names
|
||||
- resets
|
||||
- reset-names
|
||||
- "#thermal-sensor-cells"
|
||||
|
||||
additionalProperties: false
|
||||
|
|
|
@ -20,6 +20,7 @@ properties:
|
|||
- socionext,uniphier-pxs2-thermal
|
||||
- socionext,uniphier-ld20-thermal
|
||||
- socionext,uniphier-pxs3-thermal
|
||||
- socionext,uniphier-nx1-thermal
|
||||
|
||||
interrupts:
|
||||
maxItems: 1
|
||||
|
|
|
@ -15,6 +15,14 @@
|
|||
|
||||
#include "thermal_core.h"
|
||||
|
||||
static int user_space_bind(struct thermal_zone_device *tz)
|
||||
{
|
||||
pr_warn("Userspace governor deprecated: use thermal netlink " \
|
||||
"notification instead\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* notify_user_space - Notifies user space about thermal events
|
||||
* @tz: thermal_zone_device
|
||||
|
@ -43,5 +51,6 @@ static int notify_user_space(struct thermal_zone_device *tz, int trip)
|
|||
static struct thermal_governor thermal_gov_user_space = {
|
||||
.name = "user_space",
|
||||
.throttle = notify_user_space,
|
||||
.bind_to_tz = user_space_bind,
|
||||
};
|
||||
THERMAL_GOVERNOR_DECLARE(thermal_gov_user_space);
|
||||
|
|
|
@ -44,15 +44,21 @@ static int int3401_remove(struct platform_device *pdev)
|
|||
}
|
||||
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
static int int3401_thermal_suspend(struct device *dev)
|
||||
{
|
||||
return proc_thermal_suspend(dev);
|
||||
}
|
||||
static int int3401_thermal_resume(struct device *dev)
|
||||
{
|
||||
return proc_thermal_resume(dev);
|
||||
}
|
||||
#else
|
||||
#define int3401_thermal_suspend NULL
|
||||
#define int3401_thermal_resume NULL
|
||||
#endif
|
||||
|
||||
static SIMPLE_DEV_PM_OPS(int3401_proc_thermal_pm, NULL, int3401_thermal_resume);
|
||||
static SIMPLE_DEV_PM_OPS(int3401_proc_thermal_pm, int3401_thermal_suspend,
|
||||
int3401_thermal_resume);
|
||||
|
||||
static struct platform_driver int3401_driver = {
|
||||
.probe = int3401_add,
|
||||
|
|
|
@ -68,8 +68,7 @@ static const struct attribute_group power_limit_attribute_group = {
|
|||
.name = "power_limits"
|
||||
};
|
||||
|
||||
static ssize_t tcc_offset_degree_celsius_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
static int tcc_get_offset(void)
|
||||
{
|
||||
u64 val;
|
||||
int err;
|
||||
|
@ -78,8 +77,20 @@ static ssize_t tcc_offset_degree_celsius_show(struct device *dev,
|
|||
if (err)
|
||||
return err;
|
||||
|
||||
val = (val >> 24) & 0x3f;
|
||||
return sprintf(buf, "%d\n", (int)val);
|
||||
return (val >> 24) & 0x3f;
|
||||
}
|
||||
|
||||
static ssize_t tcc_offset_degree_celsius_show(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
int tcc;
|
||||
|
||||
tcc = tcc_get_offset();
|
||||
if (tcc < 0)
|
||||
return tcc;
|
||||
|
||||
return sprintf(buf, "%d\n", tcc);
|
||||
}
|
||||
|
||||
static int tcc_offset_update(unsigned int tcc)
|
||||
|
@ -107,8 +118,6 @@ static int tcc_offset_update(unsigned int tcc)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int tcc_offset_save = -1;
|
||||
|
||||
static ssize_t tcc_offset_degree_celsius_store(struct device *dev,
|
||||
struct device_attribute *attr, const char *buf,
|
||||
size_t count)
|
||||
|
@ -131,8 +140,6 @@ static ssize_t tcc_offset_degree_celsius_store(struct device *dev,
|
|||
if (err)
|
||||
return err;
|
||||
|
||||
tcc_offset_save = tcc;
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
|
@ -345,6 +352,18 @@ void proc_thermal_remove(struct proc_thermal_device *proc_priv)
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(proc_thermal_remove);
|
||||
|
||||
static int tcc_offset_save = -1;
|
||||
|
||||
int proc_thermal_suspend(struct device *dev)
|
||||
{
|
||||
tcc_offset_save = tcc_get_offset();
|
||||
if (tcc_offset_save < 0)
|
||||
dev_warn(dev, "failed to save offset (%d)\n", tcc_offset_save);
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(proc_thermal_suspend);
|
||||
|
||||
int proc_thermal_resume(struct device *dev)
|
||||
{
|
||||
struct proc_thermal_device *proc_dev;
|
||||
|
@ -352,6 +371,7 @@ int proc_thermal_resume(struct device *dev)
|
|||
proc_dev = dev_get_drvdata(dev);
|
||||
proc_thermal_read_ppcc(proc_dev);
|
||||
|
||||
/* Do not update if saving failed */
|
||||
if (tcc_offset_save >= 0)
|
||||
tcc_offset_update(tcc_offset_save);
|
||||
|
||||
|
|
|
@ -83,6 +83,7 @@ void proc_thermal_mbox_remove(struct pci_dev *pdev);
|
|||
int processor_thermal_send_mbox_cmd(struct pci_dev *pdev, u16 cmd_id, u32 cmd_data, u32 *cmd_resp);
|
||||
int proc_thermal_add(struct device *dev, struct proc_thermal_device *priv);
|
||||
void proc_thermal_remove(struct proc_thermal_device *proc_priv);
|
||||
int proc_thermal_suspend(struct device *dev);
|
||||
int proc_thermal_resume(struct device *dev);
|
||||
int proc_thermal_mmio_add(struct pci_dev *pdev,
|
||||
struct proc_thermal_device *proc_priv,
|
||||
|
|
|
@ -314,6 +314,20 @@ static void proc_thermal_pci_remove(struct pci_dev *pdev)
|
|||
}
|
||||
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
static int proc_thermal_pci_suspend(struct device *dev)
|
||||
{
|
||||
struct pci_dev *pdev = to_pci_dev(dev);
|
||||
struct proc_thermal_device *proc_priv;
|
||||
struct proc_thermal_pci *pci_info;
|
||||
|
||||
proc_priv = pci_get_drvdata(pdev);
|
||||
pci_info = proc_priv->priv_data;
|
||||
|
||||
if (!pci_info->no_legacy)
|
||||
return proc_thermal_suspend(dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int proc_thermal_pci_resume(struct device *dev)
|
||||
{
|
||||
struct pci_dev *pdev = to_pci_dev(dev);
|
||||
|
@ -335,10 +349,12 @@ static int proc_thermal_pci_resume(struct device *dev)
|
|||
return 0;
|
||||
}
|
||||
#else
|
||||
#define proc_thermal_pci_suspend NULL
|
||||
#define proc_thermal_pci_resume NULL
|
||||
#endif
|
||||
|
||||
static SIMPLE_DEV_PM_OPS(proc_thermal_pci_pm, NULL, proc_thermal_pci_resume);
|
||||
static SIMPLE_DEV_PM_OPS(proc_thermal_pci_pm, proc_thermal_pci_suspend,
|
||||
proc_thermal_pci_resume);
|
||||
|
||||
static const struct pci_device_id proc_thermal_pci_ids[] = {
|
||||
{ PCI_DEVICE_DATA(INTEL, ADL_THERMAL, PROC_THERMAL_FEATURE_RAPL | PROC_THERMAL_FEATURE_FIVR | PROC_THERMAL_FEATURE_DVFS | PROC_THERMAL_FEATURE_MBOX) },
|
||||
|
|
|
@ -107,15 +107,21 @@ static void proc_thermal_pci_remove(struct pci_dev *pdev)
|
|||
}
|
||||
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
static int proc_thermal_pci_suspend(struct device *dev)
|
||||
{
|
||||
return proc_thermal_suspend(dev);
|
||||
}
|
||||
static int proc_thermal_pci_resume(struct device *dev)
|
||||
{
|
||||
return proc_thermal_resume(dev);
|
||||
}
|
||||
#else
|
||||
#define proc_thermal_pci_suspend NULL
|
||||
#define proc_thermal_pci_resume NULL
|
||||
#endif
|
||||
|
||||
static SIMPLE_DEV_PM_OPS(proc_thermal_pci_pm, NULL, proc_thermal_pci_resume);
|
||||
static SIMPLE_DEV_PM_OPS(proc_thermal_pci_pm, proc_thermal_pci_suspend,
|
||||
proc_thermal_pci_resume);
|
||||
|
||||
static const struct pci_device_id proc_thermal_pci_ids[] = {
|
||||
{ PCI_DEVICE_DATA(INTEL, BDW_THERMAL, 0) },
|
||||
|
|
|
@ -34,7 +34,7 @@ config QCOM_SPMI_TEMP_ALARM
|
|||
|
||||
config QCOM_LMH
|
||||
tristate "Qualcomm Limits Management Hardware"
|
||||
depends on ARCH_QCOM
|
||||
depends on ARCH_QCOM && QCOM_SCM
|
||||
help
|
||||
This enables initialization of Qualcomm limits management
|
||||
hardware(LMh). LMh allows for hardware-enforced mitigation for cpus based on
|
||||
|
|
|
@ -82,6 +82,7 @@ struct adc_tm5_data {
|
|||
const u32 full_scale_code_volt;
|
||||
unsigned int *decimation;
|
||||
unsigned int *hw_settle;
|
||||
bool is_hc;
|
||||
};
|
||||
|
||||
enum adc_tm5_cal_method {
|
||||
|
@ -146,6 +147,14 @@ static const struct adc_tm5_data adc_tm5_data_pmic = {
|
|||
64000, 128000 },
|
||||
};
|
||||
|
||||
static const struct adc_tm5_data adc_tm_hc_data_pmic = {
|
||||
.full_scale_code_volt = 0x70e4,
|
||||
.decimation = (unsigned int []) { 256, 512, 1024 },
|
||||
.hw_settle = (unsigned int []) { 0, 100, 200, 300, 400, 500, 600, 700,
|
||||
1000, 2000, 4000, 6000, 8000, 10000 },
|
||||
.is_hc = true,
|
||||
};
|
||||
|
||||
static int adc_tm5_read(struct adc_tm5_chip *adc_tm, u16 offset, u8 *data, int len)
|
||||
{
|
||||
return regmap_bulk_read(adc_tm->regmap, adc_tm->base + offset, data, len);
|
||||
|
@ -375,6 +384,29 @@ static int adc_tm5_register_tzd(struct adc_tm5_chip *adc_tm)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int adc_tm_hc_init(struct adc_tm5_chip *chip)
|
||||
{
|
||||
unsigned int i;
|
||||
u8 buf[2];
|
||||
int ret;
|
||||
|
||||
for (i = 0; i < chip->nchannels; i++) {
|
||||
if (chip->channels[i].channel >= ADC_TM5_NUM_CHANNELS) {
|
||||
dev_err(chip->dev, "Invalid channel %d\n", chip->channels[i].channel);
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
buf[0] = chip->decimation;
|
||||
buf[1] = chip->avg_samples | ADC_TM5_FAST_AVG_EN;
|
||||
|
||||
ret = adc_tm5_write(chip, ADC_TM5_ADC_DIG_PARAM, buf, sizeof(buf));
|
||||
if (ret)
|
||||
dev_err(chip->dev, "block write failed: %d\n", ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int adc_tm5_init(struct adc_tm5_chip *chip)
|
||||
{
|
||||
u8 buf[4], channels_available;
|
||||
|
@ -591,7 +623,10 @@ static int adc_tm5_probe(struct platform_device *pdev)
|
|||
return ret;
|
||||
}
|
||||
|
||||
ret = adc_tm5_init(adc_tm);
|
||||
if (adc_tm->data->is_hc)
|
||||
ret = adc_tm_hc_init(adc_tm);
|
||||
else
|
||||
ret = adc_tm5_init(adc_tm);
|
||||
if (ret) {
|
||||
dev_err(dev, "adc-tm init failed\n");
|
||||
return ret;
|
||||
|
@ -612,6 +647,10 @@ static const struct of_device_id adc_tm5_match_table[] = {
|
|||
.compatible = "qcom,spmi-adc-tm5",
|
||||
.data = &adc_tm5_data_pmic,
|
||||
},
|
||||
{
|
||||
.compatible = "qcom,spmi-adc-tm-hc",
|
||||
.data = &adc_tm_hc_data_pmic,
|
||||
},
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, adc_tm5_match_table);
|
||||
|
|
|
@ -603,22 +603,21 @@ int get_temp_tsens_valid(const struct tsens_sensor *s, int *temp)
|
|||
int ret;
|
||||
|
||||
/* VER_0 doesn't have VALID bit */
|
||||
if (tsens_version(priv) >= VER_0_1) {
|
||||
ret = regmap_field_read(priv->rf[valid_idx], &valid);
|
||||
if (ret)
|
||||
return ret;
|
||||
while (!valid) {
|
||||
/* Valid bit is 0 for 6 AHB clock cycles.
|
||||
* At 19.2MHz, 1 AHB clock is ~60ns.
|
||||
* We should enter this loop very, very rarely.
|
||||
*/
|
||||
ndelay(400);
|
||||
ret = regmap_field_read(priv->rf[valid_idx], &valid);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
if (tsens_version(priv) == VER_0)
|
||||
goto get_temp;
|
||||
|
||||
/* Valid bit is 0 for 6 AHB clock cycles.
|
||||
* At 19.2MHz, 1 AHB clock is ~60ns.
|
||||
* We should enter this loop very, very rarely.
|
||||
* Wait 1 us since it's the min of poll_timeout macro.
|
||||
* Old value was 400 ns.
|
||||
*/
|
||||
ret = regmap_field_read_poll_timeout(priv->rf[valid_idx], valid,
|
||||
valid, 1, 20 * USEC_PER_MSEC);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
get_temp:
|
||||
/* Valid bit is set, OK to read the temperature */
|
||||
*temp = tsens_hw_to_mC(s, temp_idx);
|
||||
|
||||
|
|
|
@ -34,6 +34,10 @@
|
|||
#define REG_GEN3_THCODE1 0x50
|
||||
#define REG_GEN3_THCODE2 0x54
|
||||
#define REG_GEN3_THCODE3 0x58
|
||||
#define REG_GEN3_PTAT1 0x5c
|
||||
#define REG_GEN3_PTAT2 0x60
|
||||
#define REG_GEN3_PTAT3 0x64
|
||||
#define REG_GEN3_THSCP 0x68
|
||||
|
||||
/* IRQ{STR,MSK,EN} bits */
|
||||
#define IRQ_TEMP1 BIT(0)
|
||||
|
@ -55,6 +59,9 @@
|
|||
#define THCTR_PONM BIT(6)
|
||||
#define THCTR_THSST BIT(0)
|
||||
|
||||
/* THSCP bits */
|
||||
#define THSCP_COR_PARA_VLD (BIT(15) | BIT(14))
|
||||
|
||||
#define CTEMP_MASK 0xFFF
|
||||
|
||||
#define MCELSIUS(temp) ((temp) * 1000)
|
||||
|
@ -62,15 +69,6 @@
|
|||
|
||||
#define TSC_MAX_NUM 5
|
||||
|
||||
/* default THCODE values if FUSEs are missing */
|
||||
static const int thcodes[TSC_MAX_NUM][3] = {
|
||||
{ 3397, 2800, 2221 },
|
||||
{ 3393, 2795, 2216 },
|
||||
{ 3389, 2805, 2237 },
|
||||
{ 3415, 2694, 2195 },
|
||||
{ 3356, 2724, 2244 },
|
||||
};
|
||||
|
||||
/* Structure for thermal temperature calculation */
|
||||
struct equation_coefs {
|
||||
int a1;
|
||||
|
@ -84,13 +82,14 @@ struct rcar_gen3_thermal_tsc {
|
|||
struct thermal_zone_device *zone;
|
||||
struct equation_coefs coef;
|
||||
int tj_t;
|
||||
unsigned int id; /* thermal channel id */
|
||||
int thcode[3];
|
||||
};
|
||||
|
||||
struct rcar_gen3_thermal_priv {
|
||||
struct rcar_gen3_thermal_tsc *tscs[TSC_MAX_NUM];
|
||||
unsigned int num_tscs;
|
||||
void (*thermal_init)(struct rcar_gen3_thermal_tsc *tsc);
|
||||
int ptat[3];
|
||||
};
|
||||
|
||||
static inline u32 rcar_gen3_thermal_read(struct rcar_gen3_thermal_tsc *tsc,
|
||||
|
@ -133,8 +132,8 @@ static inline void rcar_gen3_thermal_write(struct rcar_gen3_thermal_tsc *tsc,
|
|||
/* no idea where these constants come from */
|
||||
#define TJ_3 -41
|
||||
|
||||
static void rcar_gen3_thermal_calc_coefs(struct rcar_gen3_thermal_tsc *tsc,
|
||||
int *ptat, const int *thcode,
|
||||
static void rcar_gen3_thermal_calc_coefs(struct rcar_gen3_thermal_priv *priv,
|
||||
struct rcar_gen3_thermal_tsc *tsc,
|
||||
int ths_tj_1)
|
||||
{
|
||||
/* TODO: Find documentation and document constant calculation formula */
|
||||
|
@ -143,16 +142,16 @@ static void rcar_gen3_thermal_calc_coefs(struct rcar_gen3_thermal_tsc *tsc,
|
|||
* Division is not scaled in BSP and if scaled it might overflow
|
||||
* the dividend (4095 * 4095 << 14 > INT_MAX) so keep it unscaled
|
||||
*/
|
||||
tsc->tj_t = (FIXPT_INT((ptat[1] - ptat[2]) * (ths_tj_1 - TJ_3))
|
||||
/ (ptat[0] - ptat[2])) + FIXPT_INT(TJ_3);
|
||||
tsc->tj_t = (FIXPT_INT((priv->ptat[1] - priv->ptat[2]) * (ths_tj_1 - TJ_3))
|
||||
/ (priv->ptat[0] - priv->ptat[2])) + FIXPT_INT(TJ_3);
|
||||
|
||||
tsc->coef.a1 = FIXPT_DIV(FIXPT_INT(thcode[1] - thcode[2]),
|
||||
tsc->coef.a1 = FIXPT_DIV(FIXPT_INT(tsc->thcode[1] - tsc->thcode[2]),
|
||||
tsc->tj_t - FIXPT_INT(TJ_3));
|
||||
tsc->coef.b1 = FIXPT_INT(thcode[2]) - tsc->coef.a1 * TJ_3;
|
||||
tsc->coef.b1 = FIXPT_INT(tsc->thcode[2]) - tsc->coef.a1 * TJ_3;
|
||||
|
||||
tsc->coef.a2 = FIXPT_DIV(FIXPT_INT(thcode[1] - thcode[0]),
|
||||
tsc->coef.a2 = FIXPT_DIV(FIXPT_INT(tsc->thcode[1] - tsc->thcode[0]),
|
||||
tsc->tj_t - FIXPT_INT(ths_tj_1));
|
||||
tsc->coef.b2 = FIXPT_INT(thcode[0]) - tsc->coef.a2 * ths_tj_1;
|
||||
tsc->coef.b2 = FIXPT_INT(tsc->thcode[0]) - tsc->coef.a2 * ths_tj_1;
|
||||
}
|
||||
|
||||
static int rcar_gen3_thermal_round(int temp)
|
||||
|
@ -174,7 +173,7 @@ static int rcar_gen3_thermal_get_temp(void *devdata, int *temp)
|
|||
/* Read register and convert to mili Celsius */
|
||||
reg = rcar_gen3_thermal_read(tsc, REG_GEN3_TEMP) & CTEMP_MASK;
|
||||
|
||||
if (reg <= thcodes[tsc->id][1])
|
||||
if (reg <= tsc->thcode[1])
|
||||
val = FIXPT_DIV(FIXPT_INT(reg) - tsc->coef.b1,
|
||||
tsc->coef.a1);
|
||||
else
|
||||
|
@ -253,6 +252,64 @@ static const struct soc_device_attribute r8a7795es1[] = {
|
|||
{ /* sentinel */ }
|
||||
};
|
||||
|
||||
static bool rcar_gen3_thermal_read_fuses(struct rcar_gen3_thermal_priv *priv)
|
||||
{
|
||||
unsigned int i;
|
||||
u32 thscp;
|
||||
|
||||
/* If fuses are not set, fallback to pseudo values. */
|
||||
thscp = rcar_gen3_thermal_read(priv->tscs[0], REG_GEN3_THSCP);
|
||||
if ((thscp & THSCP_COR_PARA_VLD) != THSCP_COR_PARA_VLD) {
|
||||
/* Default THCODE values in case FUSEs are not set. */
|
||||
static const int thcodes[TSC_MAX_NUM][3] = {
|
||||
{ 3397, 2800, 2221 },
|
||||
{ 3393, 2795, 2216 },
|
||||
{ 3389, 2805, 2237 },
|
||||
{ 3415, 2694, 2195 },
|
||||
{ 3356, 2724, 2244 },
|
||||
};
|
||||
|
||||
priv->ptat[0] = 2631;
|
||||
priv->ptat[1] = 1509;
|
||||
priv->ptat[2] = 435;
|
||||
|
||||
for (i = 0; i < priv->num_tscs; i++) {
|
||||
struct rcar_gen3_thermal_tsc *tsc = priv->tscs[i];
|
||||
|
||||
tsc->thcode[0] = thcodes[i][0];
|
||||
tsc->thcode[1] = thcodes[i][1];
|
||||
tsc->thcode[2] = thcodes[i][2];
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the pseudo calibration points with fused values.
|
||||
* PTAT is shared between all TSCs but only fused for the first
|
||||
* TSC while THCODEs are fused for each TSC.
|
||||
*/
|
||||
priv->ptat[0] = rcar_gen3_thermal_read(priv->tscs[0], REG_GEN3_PTAT1) &
|
||||
GEN3_FUSE_MASK;
|
||||
priv->ptat[1] = rcar_gen3_thermal_read(priv->tscs[0], REG_GEN3_PTAT2) &
|
||||
GEN3_FUSE_MASK;
|
||||
priv->ptat[2] = rcar_gen3_thermal_read(priv->tscs[0], REG_GEN3_PTAT3) &
|
||||
GEN3_FUSE_MASK;
|
||||
|
||||
for (i = 0; i < priv->num_tscs; i++) {
|
||||
struct rcar_gen3_thermal_tsc *tsc = priv->tscs[i];
|
||||
|
||||
tsc->thcode[0] = rcar_gen3_thermal_read(tsc, REG_GEN3_THCODE1) &
|
||||
GEN3_FUSE_MASK;
|
||||
tsc->thcode[1] = rcar_gen3_thermal_read(tsc, REG_GEN3_THCODE2) &
|
||||
GEN3_FUSE_MASK;
|
||||
tsc->thcode[2] = rcar_gen3_thermal_read(tsc, REG_GEN3_THCODE3) &
|
||||
GEN3_FUSE_MASK;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void rcar_gen3_thermal_init_r8a7795es1(struct rcar_gen3_thermal_tsc *tsc)
|
||||
{
|
||||
rcar_gen3_thermal_write(tsc, REG_GEN3_CTSR, CTSR_THBGR);
|
||||
|
@ -401,10 +458,6 @@ static int rcar_gen3_thermal_probe(struct platform_device *pdev)
|
|||
unsigned int i;
|
||||
int ret;
|
||||
|
||||
/* default values if FUSEs are missing */
|
||||
/* TODO: Read values from hardware on supported platforms */
|
||||
int ptat[3] = { 2631, 1509, 435 };
|
||||
|
||||
priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
|
||||
if (!priv)
|
||||
return -ENOMEM;
|
||||
|
@ -439,9 +492,17 @@ static int rcar_gen3_thermal_probe(struct platform_device *pdev)
|
|||
ret = PTR_ERR(tsc->base);
|
||||
goto error_unregister;
|
||||
}
|
||||
tsc->id = i;
|
||||
|
||||
priv->tscs[i] = tsc;
|
||||
}
|
||||
|
||||
priv->num_tscs = i;
|
||||
|
||||
if (!rcar_gen3_thermal_read_fuses(priv))
|
||||
dev_info(dev, "No calibration values fused, fallback to driver values\n");
|
||||
|
||||
for (i = 0; i < priv->num_tscs; i++) {
|
||||
struct rcar_gen3_thermal_tsc *tsc = priv->tscs[i];
|
||||
|
||||
zone = devm_thermal_zone_of_sensor_register(dev, i, tsc,
|
||||
&rcar_gen3_tz_of_ops);
|
||||
|
@ -453,7 +514,7 @@ static int rcar_gen3_thermal_probe(struct platform_device *pdev)
|
|||
tsc->zone = zone;
|
||||
|
||||
priv->thermal_init(tsc);
|
||||
rcar_gen3_thermal_calc_coefs(tsc, ptat, thcodes[i], *ths_tj_1);
|
||||
rcar_gen3_thermal_calc_coefs(priv, tsc, *ths_tj_1);
|
||||
|
||||
tsc->zone->tzp->no_hwmon = false;
|
||||
ret = thermal_add_hwmon_sysfs(tsc->zone);
|
||||
|
@ -471,8 +532,6 @@ static int rcar_gen3_thermal_probe(struct platform_device *pdev)
|
|||
dev_info(dev, "TSC%u: Loaded %d trip points\n", i, ret);
|
||||
}
|
||||
|
||||
priv->num_tscs = i;
|
||||
|
||||
if (!priv->num_tscs) {
|
||||
ret = -ENODEV;
|
||||
goto error_unregister;
|
||||
|
|
|
@ -1383,7 +1383,7 @@ static int rockchip_thermal_probe(struct platform_device *pdev)
|
|||
if (IS_ERR(thermal->regs))
|
||||
return PTR_ERR(thermal->regs);
|
||||
|
||||
thermal->reset = devm_reset_control_get(&pdev->dev, "tsadc-apb");
|
||||
thermal->reset = devm_reset_control_array_get(&pdev->dev, false, false);
|
||||
if (IS_ERR(thermal->reset)) {
|
||||
error = PTR_ERR(thermal->reset);
|
||||
dev_err(&pdev->dev, "failed to get tsadc reset: %d\n", error);
|
||||
|
|
|
@ -375,10 +375,12 @@ static void handle_thermal_trip(struct thermal_zone_device *tz, int trip)
|
|||
if (tz->last_temperature != THERMAL_TEMP_INVALID) {
|
||||
if (tz->last_temperature < trip_temp &&
|
||||
tz->temperature >= trip_temp)
|
||||
thermal_notify_tz_trip_up(tz->id, trip);
|
||||
thermal_notify_tz_trip_up(tz->id, trip,
|
||||
tz->temperature);
|
||||
if (tz->last_temperature >= trip_temp &&
|
||||
tz->temperature < (trip_temp - hyst))
|
||||
thermal_notify_tz_trip_down(tz->id, trip);
|
||||
thermal_notify_tz_trip_down(tz->id, trip,
|
||||
tz->temperature);
|
||||
}
|
||||
|
||||
if (type == THERMAL_TRIP_CRITICAL || type == THERMAL_TRIP_HOT)
|
||||
|
@ -887,7 +889,7 @@ __thermal_cooling_device_register(struct device_node *np,
|
|||
{
|
||||
struct thermal_cooling_device *cdev;
|
||||
struct thermal_zone_device *pos = NULL;
|
||||
int ret;
|
||||
int id, ret;
|
||||
|
||||
if (!ops || !ops->get_max_state || !ops->get_cur_state ||
|
||||
!ops->set_cur_state)
|
||||
|
@ -901,6 +903,11 @@ __thermal_cooling_device_register(struct device_node *np,
|
|||
if (ret < 0)
|
||||
goto out_kfree_cdev;
|
||||
cdev->id = ret;
|
||||
id = ret;
|
||||
|
||||
ret = dev_set_name(&cdev->device, "cooling_device%d", cdev->id);
|
||||
if (ret)
|
||||
goto out_ida_remove;
|
||||
|
||||
cdev->type = kstrdup(type ? type : "", GFP_KERNEL);
|
||||
if (!cdev->type) {
|
||||
|
@ -916,7 +923,6 @@ __thermal_cooling_device_register(struct device_node *np,
|
|||
cdev->device.class = &thermal_class;
|
||||
cdev->devdata = devdata;
|
||||
thermal_cooling_device_setup_sysfs(cdev);
|
||||
dev_set_name(&cdev->device, "cooling_device%d", cdev->id);
|
||||
ret = device_register(&cdev->device);
|
||||
if (ret)
|
||||
goto out_kfree_type;
|
||||
|
@ -941,8 +947,9 @@ __thermal_cooling_device_register(struct device_node *np,
|
|||
out_kfree_type:
|
||||
kfree(cdev->type);
|
||||
put_device(&cdev->device);
|
||||
cdev = NULL;
|
||||
out_ida_remove:
|
||||
ida_simple_remove(&thermal_cdev_ida, cdev->id);
|
||||
ida_simple_remove(&thermal_cdev_ida, id);
|
||||
out_kfree_cdev:
|
||||
kfree(cdev);
|
||||
return ERR_PTR(ret);
|
||||
|
@ -1227,6 +1234,10 @@ thermal_zone_device_register(const char *type, int trips, int mask,
|
|||
tz->id = id;
|
||||
strlcpy(tz->type, type, sizeof(tz->type));
|
||||
|
||||
result = dev_set_name(&tz->device, "thermal_zone%d", tz->id);
|
||||
if (result)
|
||||
goto remove_id;
|
||||
|
||||
if (!ops->critical)
|
||||
ops->critical = thermal_zone_device_critical;
|
||||
|
||||
|
@ -1248,7 +1259,6 @@ thermal_zone_device_register(const char *type, int trips, int mask,
|
|||
/* 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);
|
||||
if (result)
|
||||
goto release_device;
|
||||
|
|
|
@ -34,7 +34,7 @@ static int thermal_mmio_get_temperature(void *private, int *temp)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static struct thermal_zone_of_device_ops thermal_mmio_ops = {
|
||||
static const struct thermal_zone_of_device_ops thermal_mmio_ops = {
|
||||
.get_temp = thermal_mmio_get_temperature,
|
||||
};
|
||||
|
||||
|
|
|
@ -121,7 +121,8 @@ static int thermal_genl_event_tz(struct param *p)
|
|||
static int thermal_genl_event_tz_trip_up(struct param *p)
|
||||
{
|
||||
if (nla_put_u32(p->msg, THERMAL_GENL_ATTR_TZ_ID, p->tz_id) ||
|
||||
nla_put_u32(p->msg, THERMAL_GENL_ATTR_TZ_TRIP_ID, p->trip_id))
|
||||
nla_put_u32(p->msg, THERMAL_GENL_ATTR_TZ_TRIP_ID, p->trip_id) ||
|
||||
nla_put_u32(p->msg, THERMAL_GENL_ATTR_TZ_TEMP, p->temp))
|
||||
return -EMSGSIZE;
|
||||
|
||||
return 0;
|
||||
|
@ -285,16 +286,16 @@ int thermal_notify_tz_disable(int tz_id)
|
|||
return thermal_genl_send_event(THERMAL_GENL_EVENT_TZ_DISABLE, &p);
|
||||
}
|
||||
|
||||
int thermal_notify_tz_trip_down(int tz_id, int trip_id)
|
||||
int thermal_notify_tz_trip_down(int tz_id, int trip_id, int temp)
|
||||
{
|
||||
struct param p = { .tz_id = tz_id, .trip_id = trip_id };
|
||||
struct param p = { .tz_id = tz_id, .trip_id = trip_id, .temp = temp };
|
||||
|
||||
return thermal_genl_send_event(THERMAL_GENL_EVENT_TZ_TRIP_DOWN, &p);
|
||||
}
|
||||
|
||||
int thermal_notify_tz_trip_up(int tz_id, int trip_id)
|
||||
int thermal_notify_tz_trip_up(int tz_id, int trip_id, int temp)
|
||||
{
|
||||
struct param p = { .tz_id = tz_id, .trip_id = trip_id };
|
||||
struct param p = { .tz_id = tz_id, .trip_id = trip_id, .temp = temp };
|
||||
|
||||
return thermal_genl_send_event(THERMAL_GENL_EVENT_TZ_TRIP_UP, &p);
|
||||
}
|
||||
|
|
|
@ -11,8 +11,8 @@ int thermal_notify_tz_create(int tz_id, const char *name);
|
|||
int thermal_notify_tz_delete(int tz_id);
|
||||
int thermal_notify_tz_enable(int tz_id);
|
||||
int thermal_notify_tz_disable(int tz_id);
|
||||
int thermal_notify_tz_trip_down(int tz_id, int id);
|
||||
int thermal_notify_tz_trip_up(int tz_id, int id);
|
||||
int thermal_notify_tz_trip_down(int tz_id, int id, int temp);
|
||||
int thermal_notify_tz_trip_up(int tz_id, int id, int temp);
|
||||
int thermal_notify_tz_trip_delete(int tz_id, int id);
|
||||
int thermal_notify_tz_trip_add(int tz_id, int id, int type,
|
||||
int temp, int hyst);
|
||||
|
@ -49,12 +49,12 @@ static inline int thermal_notify_tz_disable(int tz_id)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static inline int thermal_notify_tz_trip_down(int tz_id, int id)
|
||||
static inline int thermal_notify_tz_trip_down(int tz_id, int id, int temp)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int thermal_notify_tz_trip_up(int tz_id, int id)
|
||||
static inline int thermal_notify_tz_trip_up(int tz_id, int id, int temp)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -610,6 +610,9 @@ cur_state_store(struct device *dev, struct device_attribute *attr,
|
|||
unsigned long state;
|
||||
int result;
|
||||
|
||||
dev_warn_once(&cdev->device,
|
||||
"Setting cooling device state is deprecated\n");
|
||||
|
||||
if (sscanf(buf, "%ld\n", &state) != 1)
|
||||
return -EINVAL;
|
||||
|
||||
|
|
|
@ -358,6 +358,10 @@ static const struct of_device_id uniphier_tm_dt_ids[] = {
|
|||
.compatible = "socionext,uniphier-pxs3-thermal",
|
||||
.data = &uniphier_ld20_tm_data,
|
||||
},
|
||||
{
|
||||
.compatible = "socionext,uniphier-nx1-thermal",
|
||||
.data = &uniphier_ld20_tm_data,
|
||||
},
|
||||
{ /* sentinel */ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, uniphier_tm_dt_ids);
|
||||
|
|
Загрузка…
Ссылка в новой задаче