Commit 8d7868c4 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'thermal-6.5-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm

Pull thermal control updates from Rafael Wysocki:
 "These extend the int340x thermal driver, add thermal DT bindings for
  some Qcom platforms, add DT bindings and support for Armada AP807 and
  MSM8909, allow selecting the bang-bang thermal governor as the default
  one, address issues in several thermal drivers for ARM platforms and
  clean up code.

  Specifics:

   - Add new IOCTLs to the int340x thermal driver to allow user space to
     retrieve the Passive v2 thermal table (Srinivas Pandruvada)

   - Add DT bindings for SM6375, MSM8226 and QCM2290 Qcom platforms
     (Konrad Dybcio)

   - Add DT bindings and support for QCom MSM8226 (Matti Lehtimäki)

   - Add DT bindings for QCom ipq9574 (Praveenkumar I)

   - Convert bcm2835 DT bindings to the yaml schema (Stefan Wahren)

   - Allow selecting the bang-bang governor as default (Thierry Reding)

   - Refactor and prepare the code to set the scene for RCar Gen4
     (Wolfram Sang)

   - Clean up and fix the QCom tsens drivers. Add DT bindings and
     calibration for the MSM8909 platform (Stephan Gerhold)

   - Revert a patch introducing a wrong usage of devm_of_iomap() on the
     Mediatek platform (Ricardo Cañuelo)

   - Fix the clock vs reset ordering in order to conform to the
     documentation on the sun8i (Christophe JAILLET)

   - Prevent setting up undocumented registers, enable the only
     described sensors and add the version 2.1 on the Qoriq sensor (Peng
     Fan)

   - Add DT bindings and support for the Armada AP807 (Alex Leibovich)

   - Update the mlx5 driver with the recent thermal changes (Daniel
     Lezcano)

   - Convert to platform remove callback returning void on STM32 (Uwe
     Kleine-König)

   - Add an error information printing for devm_thermal_add_hwmon_sysfs()
     and remove the error from the Sun8i, Amlogic, i.MX, TI, K3, Tegra,
     Qoriq, Mediateka and QCom (Yangtao Li)

   - Register as hwmon sensor for the Generic ADC (Chen-Yu Tsai)

   - Use the dev_err_probe() function in the QCom tsens alarm driver
     (Luca Weiss)"

* tag 'thermal-6.5-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm: (39 commits)
  thermal/drivers/qcom/temp-alarm: Use dev_err_probe
  thermal/drivers/generic-adc: Register thermal zones as hwmon sensors
  thermal/drivers/mediatek/lvts_thermal: Remove redundant msg in lvts_ctrl_start()
  thermal/drivers/qcom: Remove redundant msg at probe time
  thermal/drivers/ti-soc: Remove redundant msg in ti_thermal_expose_sensor()
  thermal/drivers/qoriq: Remove redundant msg in qoriq_tmu_register_tmu_zone()
  thermal/drivers/tegra: Remove redundant msg in tegra_tsensor_register_channel()
  drivers/thermal/k3: Remove redundant msg in k3_bandgap_probe()
  thermal/drivers/imx: Remove redundant msg in imx8mm_tmu_probe() and imx_sc_thermal_probe()
  thermal/drivers/amlogic: Remove redundant msg in amlogic_thermal_probe()
  thermal/drivers/sun8i: Remove redundant msg in sun8i_ths_register()
  thermal/hwmon: Add error information printing for devm_thermal_add_hwmon_sysfs()
  thermal/drivers/stm32: Convert to platform remove callback returning void
  net/mlx5: Update the driver with the recent thermal changes
  thermal/drivers/armada: Add support for AP807 thermal data
  dt-bindings: armada-thermal: Add armada-ap807-thermal compatible
  thermal/drivers/qoriq: Support version 2.1
  thermal/drivers/qoriq: Only enable supported sensors
  thermal/drivers/qoriq: No need to program site adjustment register
  thermal/drivers/mediatek/lvts_thermal: Register thermal zones as hwmon sensors
  ...
parents 40e8e98f a8460ba5
......@@ -8,6 +8,7 @@ Required properties:
* marvell,armada380-thermal
* marvell,armadaxp-thermal
* marvell,armada-ap806-thermal
* marvell,armada-ap807-thermal
* marvell,armada-cp110-thermal
Note: these bindings are deprecated for AP806/CP110 and should instead
......
Binding for Thermal Sensor driver for BCM2835 SoCs.
Required parameters:
-------------------
compatible: should be one of: "brcm,bcm2835-thermal",
"brcm,bcm2836-thermal" or "brcm,bcm2837-thermal"
reg: Address range of the thermal registers.
clocks: Phandle of the clock used by the thermal sensor.
#thermal-sensor-cells: should be 0 (see Documentation/devicetree/bindings/thermal/thermal-sensor.yaml)
Example:
thermal-zones {
cpu_thermal: cpu-thermal {
polling-delay-passive = <0>;
polling-delay = <1000>;
thermal-sensors = <&thermal>;
trips {
cpu-crit {
temperature = <80000>;
hysteresis = <0>;
type = "critical";
};
};
coefficients = <(-538) 407000>;
cooling-maps {
};
};
};
thermal: thermal@7e212000 {
compatible = "brcm,bcm2835-thermal";
reg = <0x7e212000 0x8>;
clocks = <&clocks BCM2835_CLOCK_TSENS>;
#thermal-sensor-cells = <0>;
};
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/thermal/brcm,bcm2835-thermal.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Broadcom BCM2835 thermal sensor
maintainers:
- Stefan Wahren <stefan.wahren@i2se.com>
allOf:
- $ref: thermal-sensor.yaml#
properties:
compatible:
enum:
- brcm,bcm2835-thermal
- brcm,bcm2836-thermal
- brcm,bcm2837-thermal
reg:
maxItems: 1
clocks:
maxItems: 1
"#thermal-sensor-cells":
const: 0
unevaluatedProperties: false
required:
- compatible
- reg
- clocks
- '#thermal-sensor-cells'
examples:
- |
#include <dt-bindings/clock/bcm2835.h>
thermal@7e212000 {
compatible = "brcm,bcm2835-thermal";
reg = <0x7e212000 0x8>;
clocks = <&clocks BCM2835_CLOCK_TSENS>;
#thermal-sensor-cells = <0>;
};
......@@ -29,6 +29,8 @@ properties:
items:
- enum:
- qcom,mdm9607-tsens
- qcom,msm8226-tsens
- qcom,msm8909-tsens
- qcom,msm8916-tsens
- qcom,msm8939-tsens
- qcom,msm8974-tsens
......@@ -48,6 +50,7 @@ properties:
- qcom,msm8953-tsens
- qcom,msm8996-tsens
- qcom,msm8998-tsens
- qcom,qcm2290-tsens
- qcom,sc7180-tsens
- qcom,sc7280-tsens
- qcom,sc8180x-tsens
......@@ -56,6 +59,7 @@ properties:
- qcom,sdm845-tsens
- qcom,sm6115-tsens
- qcom,sm6350-tsens
- qcom,sm6375-tsens
- qcom,sm8150-tsens
- qcom,sm8250-tsens
- qcom,sm8350-tsens
......@@ -67,6 +71,12 @@ properties:
enum:
- qcom,ipq8074-tsens
- description: v2 of TSENS with combined interrupt
items:
- enum:
- qcom,ipq9574-tsens
- const: qcom,ipq8074-tsens
reg:
items:
- description: TM registers
......@@ -223,12 +233,7 @@ allOf:
contains:
enum:
- qcom,ipq8064-tsens
- qcom,mdm9607-tsens
- qcom,msm8916-tsens
- qcom,msm8960-tsens
- qcom,msm8974-tsens
- qcom,msm8976-tsens
- qcom,qcs404-tsens
- qcom,tsens-v0_1
- qcom,tsens-v1
then:
......@@ -244,22 +249,7 @@ allOf:
properties:
compatible:
contains:
enum:
- qcom,msm8953-tsens
- qcom,msm8996-tsens
- qcom,msm8998-tsens
- qcom,sc7180-tsens
- qcom,sc7280-tsens
- qcom,sc8180x-tsens
- qcom,sc8280xp-tsens
- qcom,sdm630-tsens
- qcom,sdm845-tsens
- qcom,sm6350-tsens
- qcom,sm8150-tsens
- qcom,sm8250-tsens
- qcom,sm8350-tsens
- qcom,sm8450-tsens
- qcom,tsens-v2
const: qcom,tsens-v2
then:
properties:
interrupts:
......
......@@ -45,7 +45,7 @@ static int mlx5_thermal_get_mtmp_temp(struct mlx5_core_dev *mdev, u32 id, int *p
static int mlx5_thermal_get_temp(struct thermal_zone_device *tzdev,
int *p_temp)
{
struct mlx5_thermal *thermal = tzdev->devdata;
struct mlx5_thermal *thermal = thermal_zone_device_priv(tzdev);
struct mlx5_core_dev *mdev = thermal->mdev;
int err;
......@@ -81,7 +81,8 @@ int mlx5_thermal_init(struct mlx5_core_dev *mdev)
return -ENOMEM;
thermal->mdev = mdev;
thermal->tzdev = thermal_zone_device_register(data,
thermal->tzdev = thermal_zone_device_register_with_trips(data,
NULL,
MLX5_THERMAL_NUM_TRIPS,
MLX5_THERMAL_TRIP_MASK,
thermal,
......
......@@ -130,6 +130,14 @@ config THERMAL_DEFAULT_GOV_POWER_ALLOCATOR
system and device power allocation. This governor can only
operate on cooling devices that implement the power API.
config THERMAL_DEFAULT_GOV_BANG_BANG
bool "bang_bang"
depends on THERMAL_GOV_BANG_BANG
help
Use the bang_bang governor as default. This throttles the
devices one step at the time, taking into account the trip
point hysteresis.
endchoice
config THERMAL_GOV_FAIR_SHARE
......
......@@ -282,8 +282,7 @@ static int amlogic_thermal_probe(struct platform_device *pdev)
return ret;
}
if (devm_thermal_add_hwmon_sysfs(&pdev->dev, pdata->tzd))
dev_warn(&pdev->dev, "Failed to add hwmon sysfs attributes\n");
devm_thermal_add_hwmon_sysfs(&pdev->dev, pdata->tzd);
ret = amlogic_thermal_initialize(pdata);
if (ret)
......
......@@ -231,7 +231,7 @@ static void armada380_init(struct platform_device *pdev,
regmap_write(priv->syscon, data->syscon_control0_off, reg);
}
static void armada_ap806_init(struct platform_device *pdev,
static void armada_ap80x_init(struct platform_device *pdev,
struct armada_thermal_priv *priv)
{
struct armada_thermal_data *data = priv->data;
......@@ -614,7 +614,7 @@ static const struct armada_thermal_data armada380_data = {
};
static const struct armada_thermal_data armada_ap806_data = {
.init = armada_ap806_init,
.init = armada_ap80x_init,
.is_valid_bit = BIT(16),
.temp_shift = 0,
.temp_mask = 0x3ff,
......@@ -637,6 +637,30 @@ static const struct armada_thermal_data armada_ap806_data = {
.cpu_nr = 4,
};
static const struct armada_thermal_data armada_ap807_data = {
.init = armada_ap80x_init,
.is_valid_bit = BIT(16),
.temp_shift = 0,
.temp_mask = 0x3ff,
.thresh_shift = 3,
.hyst_shift = 19,
.hyst_mask = 0x3,
.coef_b = -128900LL,
.coef_m = 394ULL,
.coef_div = 1,
.inverted = true,
.signed_sample = true,
.syscon_control0_off = 0x84,
.syscon_control1_off = 0x88,
.syscon_status_off = 0x8C,
.dfx_irq_cause_off = 0x108,
.dfx_irq_mask_off = 0x10C,
.dfx_overheat_irq = BIT(22),
.dfx_server_irq_mask_off = 0x104,
.dfx_server_irq_en = BIT(1),
.cpu_nr = 4,
};
static const struct armada_thermal_data armada_cp110_data = {
.init = armada_cp110_init,
.is_valid_bit = BIT(10),
......@@ -680,6 +704,10 @@ static const struct of_device_id armada_thermal_id_table[] = {
.compatible = "marvell,armada-ap806-thermal",
.data = &armada_ap806_data,
},
{
.compatible = "marvell,armada-ap807-thermal",
.data = &armada_ap807_data,
},
{
.compatible = "marvell,armada-cp110-thermal",
.data = &armada_cp110_data,
......
......@@ -343,8 +343,7 @@ static int imx8mm_tmu_probe(struct platform_device *pdev)
}
tmu->sensors[i].hw_id = i;
if (devm_thermal_add_hwmon_sysfs(&pdev->dev, tmu->sensors[i].tzd))
dev_warn(&pdev->dev, "failed to add hwmon sysfs attributes\n");
devm_thermal_add_hwmon_sysfs(&pdev->dev, tmu->sensors[i].tzd);
}
platform_set_drvdata(pdev, tmu);
......
......@@ -116,8 +116,7 @@ static int imx_sc_thermal_probe(struct platform_device *pdev)
return ret;
}
if (devm_thermal_add_hwmon_sysfs(&pdev->dev, sensor->tzd))
dev_warn(&pdev->dev, "failed to add hwmon sysfs attributes\n");
devm_thermal_add_hwmon_sysfs(&pdev->dev, sensor->tzd);
}
return 0;
......
......@@ -203,6 +203,151 @@ int acpi_parse_art(acpi_handle handle, int *art_count, struct art **artp,
}
EXPORT_SYMBOL(acpi_parse_art);
/*
* acpi_parse_psvt - Passive Table (PSVT) for passive cooling
*
* @handle: ACPI handle of the device which contains PSVT
* @psvt_count: the number of valid entries resulted from parsing PSVT
* @psvtp: pointer to array of psvt entries
*
*/
static int acpi_parse_psvt(acpi_handle handle, int *psvt_count, struct psvt **psvtp)
{
struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
int nr_bad_entries = 0, revision = 0;
union acpi_object *p;
acpi_status status;
int i, result = 0;
struct psvt *psvts;
if (!acpi_has_method(handle, "PSVT"))
return -ENODEV;
status = acpi_evaluate_object(handle, "PSVT", NULL, &buffer);
if (ACPI_FAILURE(status))
return -ENODEV;
p = buffer.pointer;
if (!p || (p->type != ACPI_TYPE_PACKAGE)) {
result = -EFAULT;
goto end;
}
/* first package is the revision number */
if (p->package.count > 0) {
union acpi_object *prev = &(p->package.elements[0]);
if (prev->type == ACPI_TYPE_INTEGER)
revision = (int)prev->integer.value;
} else {
result = -EFAULT;
goto end;
}
/* Support only version 2 */
if (revision != 2) {
result = -EFAULT;
goto end;
}
*psvt_count = p->package.count - 1;
if (!*psvt_count) {
result = -EFAULT;
goto end;
}
psvts = kcalloc(*psvt_count, sizeof(*psvts), GFP_KERNEL);
if (!psvts) {
result = -ENOMEM;
goto end;
}
/* Start index is 1 because the first package is the revision number */
for (i = 1; i < p->package.count; i++) {
struct acpi_buffer psvt_int_format = { sizeof("RRNNNNNNNNNN"), "RRNNNNNNNNNN" };
struct acpi_buffer psvt_str_format = { sizeof("RRNNNNNSNNNN"), "RRNNNNNSNNNN" };
union acpi_object *package = &(p->package.elements[i]);
struct psvt *psvt = &psvts[i - 1 - nr_bad_entries];
struct acpi_buffer *psvt_format = &psvt_int_format;
struct acpi_buffer element = { 0, NULL };
union acpi_object *knob;
struct acpi_device *res;
struct psvt *psvt_ptr;
element.length = ACPI_ALLOCATE_BUFFER;
element.pointer = NULL;
if (package->package.count >= ACPI_NR_PSVT_ELEMENTS) {
knob = &(package->package.elements[ACPI_PSVT_CONTROL_KNOB]);
} else {
nr_bad_entries++;
pr_info("PSVT package %d is invalid, ignored\n", i);
continue;
}
if (knob->type == ACPI_TYPE_STRING) {
psvt_format = &psvt_str_format;
if (knob->string.length > ACPI_LIMIT_STR_MAX_LEN - 1) {
pr_info("PSVT package %d limit string len exceeds max\n", i);
knob->string.length = ACPI_LIMIT_STR_MAX_LEN - 1;
}
}
status = acpi_extract_package(&(p->package.elements[i]), psvt_format, &element);
if (ACPI_FAILURE(status)) {
nr_bad_entries++;
pr_info("PSVT package %d is invalid, ignored\n", i);
continue;
}
psvt_ptr = (struct psvt *)element.pointer;
memcpy(psvt, psvt_ptr, sizeof(*psvt));
/* The limit element can be string or U64 */
psvt->control_knob_type = (u64)knob->type;
if (knob->type == ACPI_TYPE_STRING) {
memset(&psvt->limit, 0, sizeof(u64));
strncpy(psvt->limit.string, psvt_ptr->limit.str_ptr, knob->string.length);
} else {
psvt->limit.integer = psvt_ptr->limit.integer;
}
kfree(element.pointer);
res = acpi_fetch_acpi_dev(psvt->source);
if (!res) {
nr_bad_entries++;
pr_info("Failed to get source ACPI device\n");
continue;
}
res = acpi_fetch_acpi_dev(psvt->target);
if (!res) {
nr_bad_entries++;
pr_info("Failed to get target ACPI device\n");
continue;
}
}
/* don't count bad entries */
*psvt_count -= nr_bad_entries;
if (!*psvt_count) {
result = -EFAULT;
kfree(psvts);
goto end;
}
*psvtp = psvts;
return 0;
end:
kfree(buffer.pointer);
return result;
}
/* get device name from acpi handle */
static void get_single_name(acpi_handle handle, char *name)
......@@ -289,6 +434,57 @@ static int fill_trt(char __user *ubuf)
return ret;
}
static int fill_psvt(char __user *ubuf)
{
int i, ret, count, psvt_len;
union psvt_object *psvt_user;
struct psvt *psvts;
ret = acpi_parse_psvt(acpi_thermal_rel_handle, &count, &psvts);
if (ret)
return ret;
psvt_len = count * sizeof(*psvt_user);
psvt_user = kzalloc(psvt_len, GFP_KERNEL);
if (!psvt_user) {
ret = -ENOMEM;
goto free_psvt;
}
/* now fill in user psvt data */
for (i = 0; i < count; i++) {
/* userspace psvt needs device name instead of acpi reference */
get_single_name(psvts[i].source, psvt_user[i].source_device);
get_single_name(psvts[i].target, psvt_user[i].target_device);
psvt_user[i].priority = psvts[i].priority;
psvt_user[i].sample_period = psvts[i].sample_period;
psvt_user[i].passive_temp = psvts[i].passive_temp;
psvt_user[i].source_domain = psvts[i].source_domain;
psvt_user[i].control_knob = psvts[i].control_knob;
psvt_user[i].step_size = psvts[i].step_size;
psvt_user[i].limit_coeff = psvts[i].limit_coeff;
psvt_user[i].unlimit_coeff = psvts[i].unlimit_coeff;
psvt_user[i].control_knob_type = psvts[i].control_knob_type;
if (psvt_user[i].control_knob_type == ACPI_TYPE_STRING)
strncpy(psvt_user[i].limit.string, psvts[i].limit.string,
ACPI_LIMIT_STR_MAX_LEN);
else
psvt_user[i].limit.integer = psvts[i].limit.integer;
}
if (copy_to_user(ubuf, psvt_user, psvt_len))
ret = -EFAULT;
kfree(psvt_user);
free_psvt:
kfree(psvts);
return ret;
}
static long acpi_thermal_rel_ioctl(struct file *f, unsigned int cmd,
unsigned long __arg)
{
......@@ -298,6 +494,7 @@ static long acpi_thermal_rel_ioctl(struct file *f, unsigned int cmd,
char __user *arg = (void __user *)__arg;
struct trt *trts = NULL;
struct art *arts = NULL;
struct psvt *psvts;
switch (cmd) {
case ACPI_THERMAL_GET_TRT_COUNT:
......@@ -336,6 +533,27 @@ static long acpi_thermal_rel_ioctl(struct file *f, unsigned int cmd,
case ACPI_THERMAL_GET_ART:
return fill_art(arg);
case ACPI_THERMAL_GET_PSVT_COUNT:
ret = acpi_parse_psvt(acpi_thermal_rel_handle, &count, &psvts);
if (!ret) {
kfree(psvts);
return put_user(count, (unsigned long __user *)__arg);
}
return ret;
case ACPI_THERMAL_GET_PSVT_LEN:
/* total length of the data retrieved (count * PSVT entry size) */
ret = acpi_parse_psvt(acpi_thermal_rel_handle, &count, &psvts);
length = count * sizeof(union psvt_object);
if (!ret) {
kfree(psvts);
return put_user(length, (unsigned long __user *)__arg);
}
return ret;
case ACPI_THERMAL_GET_PSVT:
return fill_psvt(arg);
default:
return -ENOTTY;
}
......
......@@ -14,6 +14,16 @@
#define ACPI_THERMAL_GET_TRT _IOR(ACPI_THERMAL_MAGIC, 5, unsigned long)
#define ACPI_THERMAL_GET_ART _IOR(ACPI_THERMAL_MAGIC, 6, unsigned long)
/*
* ACPI_THERMAL_GET_PSVT_COUNT = Number of PSVT entries
* ACPI_THERMAL_GET_PSVT_LEN = Total return data size (PSVT count x each
* PSVT entry size)
* ACPI_THERMAL_GET_PSVT = Get the data as an array of psvt_objects
*/
#define ACPI_THERMAL_GET_PSVT_LEN _IOR(ACPI_THERMAL_MAGIC, 7, unsigned long)
#define ACPI_THERMAL_GET_PSVT_COUNT _IOR(ACPI_THERMAL_MAGIC, 8, unsigned long)
#define ACPI_THERMAL_GET_PSVT _IOR(ACPI_THERMAL_MAGIC, 9, unsigned long)
struct art {
acpi_handle source;
acpi_handle target;
......@@ -43,6 +53,32 @@ struct trt {
u64 reserved4;
} __packed;
#define ACPI_NR_PSVT_ELEMENTS 12
#define ACPI_PSVT_CONTROL_KNOB 7
#define ACPI_LIMIT_STR_MAX_LEN 8
struct psvt {
acpi_handle source;
acpi_handle target;
u64 priority;
u64 sample_period;
u64 passive_temp;
u64 source_domain;
u64 control_knob;
union {
/* For limit_type = ACPI_TYPE_INTEGER */
u64 integer;
/* For limit_type = ACPI_TYPE_STRING */
char string[ACPI_LIMIT_STR_MAX_LEN];
char *str_ptr;
} limit;
u64 step_size;
u64 limit_coeff;
u64 unlimit_coeff;
/* Spec calls this field reserved, so we borrow it for type info */
u64 control_knob_type; /* ACPI_TYPE_STRING or ACPI_TYPE_INTEGER */
} __packed;
#define ACPI_NR_ART_ELEMENTS 13
/* for usrspace */
union art_object {
......@@ -77,6 +113,27 @@ union trt_object {
u64 __data[8];
};
union psvt_object {
struct {
char source_device[8];
char target_device[8];
u64 priority;
u64 sample_period;
u64 passive_temp;
u64 source_domain;
u64 control_knob;
union {
u64 integer;
char string[ACPI_LIMIT_STR_MAX_LEN];
} limit;
u64 step_size;
u64 limit_coeff;
u64 unlimit_coeff;
u64 control_knob_type;
};
u64 __data[ACPI_NR_PSVT_ELEMENTS];
};
#ifdef __KERNEL__
int acpi_thermal_rel_misc_device_add(acpi_handle handle);
int acpi_thermal_rel_misc_device_remove(acpi_handle handle);
......
......@@ -222,8 +222,7 @@ static int k3_bandgap_probe(struct platform_device *pdev)
goto err_alloc;
}
if (devm_thermal_add_hwmon_sysfs(dev, data[id].tzd))
dev_warn(dev, "Failed to add hwmon sysfs attributes\n");
devm_thermal_add_hwmon_sysfs(dev, data[id].tzd);
}
platform_set_drvdata(pdev, bgp);
......
......@@ -1222,12 +1222,7 @@ static int mtk_thermal_probe(struct platform_device *pdev)
return -ENODEV;
}
auxadc_base = devm_of_iomap(&pdev->dev, auxadc, 0, NULL);
if (IS_ERR(auxadc_base)) {
of_node_put(auxadc);
return PTR_ERR(auxadc_base);
}
auxadc_base = of_iomap(auxadc, 0);
auxadc_phys_base = of_get_phys_base(auxadc);
of_node_put(auxadc);
......@@ -1243,12 +1238,7 @@ static int mtk_thermal_probe(struct platform_device *pdev)
return -ENODEV;
}
apmixed_base = devm_of_iomap(&pdev->dev, apmixedsys, 0, NULL);
if (IS_ERR(apmixed_base)) {
of_node_put(apmixedsys);
return PTR_ERR(apmixed_base);
}
apmixed_base = of_iomap(apmixedsys, 0);
apmixed_phys_base = of_get_phys_base(apmixedsys);
of_node_put(apmixedsys);
......
......@@ -19,6 +19,8 @@
#include <linux/thermal.h>
#include <dt-bindings/thermal/mediatek,lvts-thermal.h>
#include "../thermal_hwmon.h"
#define LVTS_MONCTL0(__base) (__base + 0x0000)
#define LVTS_MONCTL1(__base) (__base + 0x0004)
#define LVTS_MONCTL2(__base) (__base + 0x0008)
......@@ -996,6 +998,8 @@ static int lvts_ctrl_start(struct device *dev, struct lvts_ctrl *lvts_ctrl)
return PTR_ERR(tz);
}
devm_thermal_add_hwmon_sysfs(dev, tz);
/*
* The thermal zone pointer will be needed in the
* interrupt handler, we store it in the sensor
......
......@@ -689,9 +689,7 @@ static int adc_tm5_register_tzd(struct adc_tm5_chip *adc_tm)
return PTR_ERR(tzd);
}
adc_tm->channels[i].tzd = tzd;
if (devm_thermal_add_hwmon_sysfs(adc_tm->dev, tzd))
dev_warn(adc_tm->dev,
"Failed to add hwmon sysfs attributes\n");
devm_thermal_add_hwmon_sysfs(adc_tm->dev, tzd);
}
return 0;
......
......@@ -411,22 +411,19 @@ static int qpnp_tm_probe(struct platform_device *pdev)
chip->base = res;
ret = qpnp_tm_read(chip, QPNP_TM_REG_TYPE, &type);
if (ret < 0) {
dev_err(&pdev->dev, "could not read type\n");
return ret;
}
if (ret < 0)
return dev_err_probe(&pdev->dev, ret,
"could not read type\n");
ret = qpnp_tm_read(chip, QPNP_TM_REG_SUBTYPE, &subtype);
if (ret < 0) {
dev_err(&pdev->dev, "could not read subtype\n");
return ret;
}
if (ret < 0)
return dev_err_probe(&pdev->dev, ret,
"could not read subtype\n");
ret = qpnp_tm_read(chip, QPNP_TM_REG_DIG_MAJOR, &dig_major);
if (ret < 0) {
dev_err(&pdev->dev, "could not read dig_major\n");
return ret;
}
if (ret < 0)
return dev_err_probe(&pdev->dev, ret,
"could not read dig_major\n");
if (type != QPNP_TM_TYPE || (subtype != QPNP_TM_SUBTYPE_GEN1
&& subtype != QPNP_TM_SUBTYPE_GEN2)) {
......@@ -448,20 +445,15 @@ static int qpnp_tm_probe(struct platform_device *pdev)
*/
chip->tz_dev = devm_thermal_of_zone_register(
&pdev->dev, 0, chip, &qpnp_tm_sensor_ops);
if (IS_ERR(chip->tz_dev)) {
dev_err(&pdev->dev, "failed to register sensor\n");
return PTR_ERR(chip->tz_dev);
}
if (IS_ERR(chip->tz_dev))
return dev_err_probe(&pdev->dev, PTR_ERR(chip->tz_dev),
"failed to register sensor\n");
ret = qpnp_tm_init(chip);
if (ret < 0) {
dev_err(&pdev->dev, "init failed\n");
return ret;
}
if (ret < 0)
return dev_err_probe(&pdev->dev, ret, "init failed\n");
if (devm_thermal_add_hwmon_sysfs(&pdev->dev, chip->tz_dev))
dev_warn(&pdev->dev,
"Failed to add hwmon sysfs attributes\n");
devm_thermal_add_hwmon_sysfs(&pdev->dev, chip->tz_dev);
ret = devm_request_threaded_irq(&pdev->dev, irq, NULL, qpnp_tm_isr,
IRQF_ONESHOT, node->name, chip);
......
......@@ -39,26 +39,6 @@ struct tsens_legacy_calibration_format tsens_8916_nvmem = {
},
};
struct tsens_legacy_calibration_format tsens_8939_nvmem = {
.base_len = 8,
.base_shift = 2,
.sp_len = 6,
.mode = { 12, 0 },
.invalid = { 12, 2 },
.base = { { 0, 0 }, { 1, 24 } },
.sp = {
{ { 12, 3 }, { 12, 9 } },
{ { 12, 15 }, { 12, 21 } },
{ { 12, 27 }, { 13, 1 } },
{ { 13, 7 }, { 13, 13 } },
{ { 13, 19 }, { 13, 25 } },
{ { 0, 8 }, { 0, 14 } },
{ { 0, 20 }, { 0, 26 } },
{ { 1, 0 }, { 1, 6 } },
{ { 1, 12 }, { 1, 18 } },
},
};
struct tsens_legacy_calibration_format tsens_8974_nvmem = {
.base_len = 8,
.base_shift = 2,
......@@ -103,22 +83,6 @@ struct tsens_legacy_calibration_format tsens_8974_backup_nvmem = {
},
};
struct tsens_legacy_calibration_format tsens_9607_nvmem = {
.base_len = 8,
.base_shift = 2,
.sp_len = 6,
.mode = { 2, 20 },
.invalid = { 2, 22 },
.base = { { 0, 0 }, { 2, 12 } },
.sp = {
{ { 0, 8 }, { 0, 14 } },
{ { 0, 20 }, { 0, 26 } },
{ { 1, 0 }, { 1, 6 } },
{ { 1, 12 }, { 1, 18 } },
{ { 2, 0 }, { 2, 6 } },
},
};
static int calibrate_8916(struct tsens_priv *priv)
{
u32 p1[5], p2[5];
......@@ -243,6 +207,39 @@ static int calibrate_8974(struct tsens_priv *priv)
return 0;
}
static int __init init_8226(struct tsens_priv *priv)
{
priv->sensor[0].slope = 2901;
priv->sensor[1].slope = 2846;
priv->sensor[2].slope = 3038;
priv->sensor[3].slope = 2955;
priv->sensor[4].slope = 2901;
priv->sensor[5].slope = 2846;
return init_common(priv);
}
static int __init init_8909(struct tsens_priv *priv)
{
int i;
for (i = 0; i < priv->num_sensors; ++i)
priv->sensor[i].slope = 3000;
priv->sensor[0].p1_calib_offset = 0;
priv->sensor[0].p2_calib_offset = 0;
priv->sensor[1].p1_calib_offset = -10;
priv->sensor[1].p2_calib_offset = -6;
priv->sensor[2].p1_calib_offset = 0;
priv->sensor[2].p2_calib_offset = 0;
priv->sensor[3].p1_calib_offset = -9;
priv->sensor[3].p2_calib_offset = -9;
priv->sensor[4].p1_calib_offset = -8;
priv->sensor[4].p2_calib_offset = -10;
return init_common(priv);
}
static int __init init_8939(struct tsens_priv *priv) {
priv->sensor[0].slope = 2911;
priv->sensor[1].slope = 2789;
......@@ -258,7 +255,28 @@ static int __init init_8939(struct tsens_priv *priv) {
return init_common(priv);
}
/* v0.1: 8916, 8939, 8974, 9607 */
static int __init init_9607(struct tsens_priv *priv)
{
int i;
for (i = 0; i < priv->num_sensors; ++i)
priv->sensor[i].slope = 3000;
priv->sensor[0].p1_calib_offset = 1;
priv->sensor[0].p2_calib_offset = 1;
priv->sensor[1].p1_calib_offset = -4;
priv->sensor[1].p2_calib_offset = -2;
priv->sensor[2].p1_calib_offset = 4;
priv->sensor[2].p2_calib_offset = 8;
priv->sensor[3].p1_calib_offset = -3;
priv->sensor[3].p2_calib_offset = -5;
priv->sensor[4].p1_calib_offset = -4;
priv->sensor[4].p2_calib_offset = -4;
return init_common(priv);
}
/* v0.1: 8226, 8909, 8916, 8939, 8974, 9607 */
static struct tsens_features tsens_v0_1_feat = {
.ver_major = VER_0_1,
......@@ -313,6 +331,32 @@ static const struct tsens_ops ops_v0_1 = {
.get_temp = get_temp_common,
};
static const struct tsens_ops ops_8226 = {
.init = init_8226,
.calibrate = tsens_calibrate_common,
.get_temp = get_temp_common,
};
struct tsens_plat_data data_8226 = {
.num_sensors = 6,
.ops = &ops_8226,
.feat = &tsens_v0_1_feat,
.fields = tsens_v0_1_regfields,
};
static const struct tsens_ops ops_8909 = {
.init = init_8909,
.calibrate = tsens_calibrate_common,
.get_temp = get_temp_common,
};
struct tsens_plat_data data_8909 = {
.num_sensors = 5,
.ops = &ops_8909,
.feat = &tsens_v0_1_feat,
.fields = tsens_v0_1_regfields,
};
static const struct tsens_ops ops_8916 = {
.init = init_common,
.calibrate = calibrate_8916,
......@@ -356,9 +400,15 @@ struct tsens_plat_data data_8974 = {
.fields = tsens_v0_1_regfields,
};
static const struct tsens_ops ops_9607 = {
.init = init_9607,
.calibrate = tsens_calibrate_common,
.get_temp = get_temp_common,
};
struct tsens_plat_data data_9607 = {
.num_sensors = 5,
.ops = &ops_v0_1,
.ops = &ops_9607,
.feat = &tsens_v0_1_feat,
.fields = tsens_v0_1_regfields,
};
......@@ -42,28 +42,6 @@ struct tsens_legacy_calibration_format tsens_qcs404_nvmem = {
},
};
struct tsens_legacy_calibration_format tsens_8976_nvmem = {
.base_len = 8,
.base_shift = 2,
.sp_len = 6,
.mode = { 4, 0 },
.invalid = { 4, 2 },
.base = { { 0, 0 }, { 2, 8 } },
.sp = {
{ { 0, 8 }, { 0, 14 } },
{ { 0, 20 }, { 0, 26 } },
{ { 1, 0 }, { 1, 6 } },
{ { 1, 12 }, { 1, 18 } },
{ { 2, 8 }, { 2, 14 } },
{ { 2, 20 }, { 2, 26 } },
{ { 3, 0 }, { 3, 6 } },
{ { 3, 12 }, { 3, 18 } },
{ { 4, 2 }, { 4, 9 } },
{ { 4, 14 }, { 4, 21 } },
{ { 4, 26 }, { 5, 1 } },
},
};
static int calibrate_v1(struct tsens_priv *priv)
{
u32 p1[10], p2[10];
......
......@@ -134,10 +134,12 @@ int tsens_read_calibration(struct tsens_priv *priv, int shift, u32 *p1, u32 *p2,
p1[i] = p1[i] + (base1 << shift);
break;
case TWO_PT_CALIB:
case TWO_PT_CALIB_NO_OFFSET:
for (i = 0; i < priv->num_sensors; i++)
p2[i] = (p2[i] + base2) << shift;
fallthrough;
case ONE_PT_CALIB2:
case ONE_PT_CALIB2_NO_OFFSET:
for (i = 0; i < priv->num_sensors; i++)
p1[i] = (p1[i] + base1) << shift;
break;
......@@ -149,6 +151,18 @@ int tsens_read_calibration(struct tsens_priv *priv, int shift, u32 *p1, u32 *p2,
}
}
/* Apply calibration offset workaround except for _NO_OFFSET modes */
switch (mode) {
case TWO_PT_CALIB:
for (i = 0; i < priv->num_sensors; i++)
p2[i] += priv->sensor[i].p2_calib_offset;
fallthrough;
case ONE_PT_CALIB2:
for (i = 0; i < priv->num_sensors; i++)
p1[i] += priv->sensor[i].p1_calib_offset;
break;
}
return mode;
}
......@@ -254,7 +268,7 @@ void compute_intercept_slope(struct tsens_priv *priv, u32 *p1,
if (!priv->sensor[i].slope)
priv->sensor[i].slope = SLOPE_DEFAULT;
if (mode == TWO_PT_CALIB) {
if (mode == TWO_PT_CALIB || mode == TWO_PT_CALIB_NO_OFFSET) {
/*
* slope (m) = adc_code2 - adc_code1 (y2 - y1)/
* temp_120_degc - temp_30_degc (x2 - x1)
......@@ -1095,6 +1109,12 @@ static const struct of_device_id tsens_table[] = {
}, {
.compatible = "qcom,mdm9607-tsens",
.data = &data_9607,
}, {
.compatible = "qcom,msm8226-tsens",
.data = &data_8226,
}, {
.compatible = "qcom,msm8909-tsens",
.data = &data_8909,
}, {
.compatible = "qcom,msm8916-tsens",
.data = &data_8916,
......@@ -1189,9 +1209,7 @@ static int tsens_register(struct tsens_priv *priv)
if (priv->ops->enable)
priv->ops->enable(priv, i);
if (devm_thermal_add_hwmon_sysfs(priv->dev, tzd))
dev_warn(priv->dev,
"Failed to add hwmon sysfs attributes\n");
devm_thermal_add_hwmon_sysfs(priv->dev, tzd);
}
/* VER_0 require to set MIN and MAX THRESH
......
......@@ -10,6 +10,8 @@
#define ONE_PT_CALIB 0x1
#define ONE_PT_CALIB2 0x2
#define TWO_PT_CALIB 0x3
#define ONE_PT_CALIB2_NO_OFFSET 0x6
#define TWO_PT_CALIB_NO_OFFSET 0x7
#define CAL_DEGC_PT1 30
#define CAL_DEGC_PT2 120
#define SLOPE_FACTOR 1000
......@@ -57,6 +59,8 @@ struct tsens_sensor {
unsigned int hw_id;
int slope;
u32 status;
int p1_calib_offset;
int p2_calib_offset;
};
/**
......@@ -635,7 +639,7 @@ int get_temp_common(const struct tsens_sensor *s, int *temp);
extern struct tsens_plat_data data_8960;
/* TSENS v0.1 targets */
extern struct tsens_plat_data data_8916, data_8939, data_8974, data_9607;
extern struct tsens_plat_data data_8226, data_8909, data_8916, data_8939, data_8974, data_9607;
/* TSENS v1 targets */
extern struct tsens_plat_data data_tsens_v1, data_8976, data_8956;
......
......@@ -31,7 +31,6 @@
#define TMR_DISABLE 0x0
#define TMR_ME 0x80000000
#define TMR_ALPF 0x0c000000
#define TMR_MSITE_ALL GENMASK(15, 0)
#define REGS_TMTMIR 0x008 /* Temperature measurement interval Register */
#define TMTMIR_DEFAULT 0x0000000f
......@@ -51,6 +50,7 @@
* Site Register
*/
#define TRITSR_V BIT(31)
#define TRITSR_TP5 BIT(9)
#define REGS_V2_TMSAR(n) (0x304 + 16 * (n)) /* TMU monitoring
* site adjustment register
*/
......@@ -105,6 +105,11 @@ static int tmu_get_temp(struct thermal_zone_device *tz, int *temp)
* within sensor range. TEMP is an 9 bit value representing
* temperature in KelVin.
*/
regmap_read(qdata->regmap, REGS_TMR, &val);
if (!(val & TMR_ME))
return -EAGAIN;
if (regmap_read_poll_timeout(qdata->regmap,
REGS_TRITSR(qsensor->id),
val,
......@@ -113,10 +118,15 @@ static int tmu_get_temp(struct thermal_zone_device *tz, int *temp)
10 * USEC_PER_MSEC))
return -ENODATA;
if (qdata->ver == TMU_VER1)
if (qdata->ver == TMU_VER1) {
*temp = (val & GENMASK(7, 0)) * MILLIDEGREE_PER_DEGREE;
} else {
if (val & TRITSR_TP5)
*temp = milli_kelvin_to_millicelsius((val & GENMASK(8, 0)) *
MILLIDEGREE_PER_DEGREE + 500);
else
*temp = kelvin_to_millicelsius(val & GENMASK(8, 0));
}
return 0;
}
......@@ -128,15 +138,7 @@ static const struct thermal_zone_device_ops tmu_tz_ops = {
static int qoriq_tmu_register_tmu_zone(struct device *dev,
struct qoriq_tmu_data *qdata)
{
int id;
if (qdata->ver == TMU_VER1) {
regmap_write(qdata->regmap, REGS_TMR,
TMR_MSITE_ALL | TMR_ME | TMR_ALPF);
} else {
regmap_write(qdata->regmap, REGS_V2_TMSR, TMR_MSITE_ALL);
regmap_write(qdata->regmap, REGS_TMR, TMR_ME | TMR_ALPF_V2);
}
int id, sites = 0;
for (id = 0; id < SITES_MAX; id++) {
struct thermal_zone_device *tzd;
......@@ -153,14 +155,24 @@ static int qoriq_tmu_register_tmu_zone(struct device *dev,
if (ret == -ENODEV)
continue;
regmap_write(qdata->regmap, REGS_TMR, TMR_DISABLE);
return ret;
}
if (devm_thermal_add_hwmon_sysfs(dev, tzd))
dev_warn(dev,
"Failed to add hwmon sysfs attributes\n");
if (qdata->ver == TMU_VER1)
sites |= 0x1 << (15 - id);
else
sites |= 0x1 << id;
devm_thermal_add_hwmon_sysfs(dev, tzd);
}
if (sites) {
if (qdata->ver == TMU_VER1) {
regmap_write(qdata->regmap, REGS_TMR, TMR_ME | TMR_ALPF | sites);
} else {
regmap_write(qdata->regmap, REGS_V2_TMSR, sites);
regmap_write(qdata->regmap, REGS_TMR, TMR_ME | TMR_ALPF_V2);
}
}
return 0;
......@@ -208,8 +220,6 @@ static int qoriq_tmu_calibration(struct device *dev,
static void qoriq_tmu_init_device(struct qoriq_tmu_data *data)
{
int i;
/* Disable interrupt, using polling instead */
regmap_write(data->regmap, REGS_TIER, TIER_DISABLE);
......@@ -220,8 +230,6 @@ static void qoriq_tmu_init_device(struct qoriq_tmu_data *data)
} else {
regmap_write(data->regmap, REGS_V2_TMTMIR, TMTMIR_DEFAULT);
regmap_write(data->regmap, REGS_V2_TEUMR(0), TEUMR0_V2);
for (i = 0; i < SITES_MAX; i++)
regmap_write(data->regmap, REGS_V2_TMSAR(i), TMSARA_V2);
}
/* Disable monitoring */
......@@ -230,7 +238,7 @@ static void qoriq_tmu_init_device(struct qoriq_tmu_data *data)
static const struct regmap_range qoriq_yes_ranges[] = {
regmap_reg_range(REGS_TMR, REGS_TSCFGR),
regmap_reg_range(REGS_TTRnCR(0), REGS_TTRnCR(3)),
regmap_reg_range(REGS_TTRnCR(0), REGS_TTRnCR(15)),
regmap_reg_range(REGS_V2_TEUMR(0), REGS_V2_TEUMR(2)),
regmap_reg_range(REGS_V2_TMSAR(0), REGS_V2_TMSAR(15)),
regmap_reg_range(REGS_IPBRR(0), REGS_IPBRR(1)),
......
......@@ -35,6 +35,12 @@
#define REG_GEN3_PTAT2 0x60
#define REG_GEN3_PTAT3 0x64
#define REG_GEN3_THSCP 0x68
#define REG_GEN4_THSFMON00 0x180
#define REG_GEN4_THSFMON01 0x184
#define REG_GEN4_THSFMON02 0x188
#define REG_GEN4_THSFMON15 0x1BC
#define REG_GEN4_THSFMON16 0x1C0
#define REG_GEN4_THSFMON17 0x1C4
/* IRQ{STR,MSK,EN} bits */
#define IRQ_TEMP1 BIT(0)
......@@ -55,6 +61,7 @@
#define MCELSIUS(temp) ((temp) * 1000)
#define GEN3_FUSE_MASK 0xFFF
#define GEN4_FUSE_MASK 0xFFF
#define TSC_MAX_NUM 5
......@@ -66,6 +73,13 @@ struct equation_coefs {
int b2;
};
struct rcar_gen3_thermal_priv;
struct rcar_thermal_info {
int ths_tj_1;
void (*read_fuses)(struct rcar_gen3_thermal_priv *priv);
};
struct rcar_gen3_thermal_tsc {
void __iomem *base;
struct thermal_zone_device *zone;
......@@ -79,6 +93,7 @@ struct rcar_gen3_thermal_priv {
struct thermal_zone_device_ops ops;
unsigned int num_tscs;
int ptat[3];
const struct rcar_thermal_info *info;
};
static inline u32 rcar_gen3_thermal_read(struct rcar_gen3_thermal_tsc *tsc,
......@@ -236,6 +251,62 @@ static irqreturn_t rcar_gen3_thermal_irq(int irq, void *data)
return IRQ_HANDLED;
}
static void rcar_gen3_thermal_read_fuses_gen3(struct rcar_gen3_thermal_priv *priv)
{
unsigned int i;
/*
* 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;
}
}
static void rcar_gen3_thermal_read_fuses_gen4(struct rcar_gen3_thermal_priv *priv)
{
unsigned int i;
/*
* 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_GEN4_THSFMON16) &
GEN4_FUSE_MASK;
priv->ptat[1] = rcar_gen3_thermal_read(priv->tscs[0], REG_GEN4_THSFMON17) &
GEN4_FUSE_MASK;
priv->ptat[2] = rcar_gen3_thermal_read(priv->tscs[0], REG_GEN4_THSFMON15) &
GEN4_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_GEN4_THSFMON01) &
GEN4_FUSE_MASK;
tsc->thcode[1] = rcar_gen3_thermal_read(tsc, REG_GEN4_THSFMON02) &
GEN4_FUSE_MASK;
tsc->thcode[2] = rcar_gen3_thermal_read(tsc, REG_GEN4_THSFMON00) &
GEN4_FUSE_MASK;
}
}
static bool rcar_gen3_thermal_read_fuses(struct rcar_gen3_thermal_priv *priv)
{
unsigned int i;
......@@ -243,7 +314,8 @@ static bool rcar_gen3_thermal_read_fuses(struct rcar_gen3_thermal_priv *priv)
/* 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) {
if (!priv->info->read_fuses ||
(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 },
......@@ -268,29 +340,7 @@ static bool rcar_gen3_thermal_read_fuses(struct rcar_gen3_thermal_priv *priv)
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;
}
priv->info->read_fuses(priv);
return true;
}
......@@ -318,52 +368,65 @@ static void rcar_gen3_thermal_init(struct rcar_gen3_thermal_priv *priv,
usleep_range(1000, 2000);
}
static const int rcar_gen3_ths_tj_1 = 126;
static const int rcar_gen3_ths_tj_1_m3_w = 116;
static const struct rcar_thermal_info rcar_m3w_thermal_info = {
.ths_tj_1 = 116,
.read_fuses = rcar_gen3_thermal_read_fuses_gen3,
};
static const struct rcar_thermal_info rcar_gen3_thermal_info = {
.ths_tj_1 = 126,
.read_fuses = rcar_gen3_thermal_read_fuses_gen3,
};
static const struct rcar_thermal_info rcar_gen4_thermal_info = {
.ths_tj_1 = 126,
.read_fuses = rcar_gen3_thermal_read_fuses_gen4,
};
static const struct of_device_id rcar_gen3_thermal_dt_ids[] = {
{
.compatible = "renesas,r8a774a1-thermal",
.data = &rcar_gen3_ths_tj_1_m3_w,
.data = &rcar_m3w_thermal_info,
},
{
.compatible = "renesas,r8a774b1-thermal",
.data = &rcar_gen3_ths_tj_1,
.data = &rcar_gen3_thermal_info,
},
{
.compatible = "renesas,r8a774e1-thermal",
.data = &rcar_gen3_ths_tj_1,
.data = &rcar_gen3_thermal_info,
},
{
.compatible = "renesas,r8a7795-thermal",
.data = &rcar_gen3_ths_tj_1,
.data = &rcar_gen3_thermal_info,
},
{
.compatible = "renesas,r8a7796-thermal",
.data = &rcar_gen3_ths_tj_1_m3_w,
.data = &rcar_m3w_thermal_info,
},
{
.compatible = "renesas,r8a77961-thermal",
.data = &rcar_gen3_ths_tj_1_m3_w,
.data = &rcar_m3w_thermal_info,
},
{
.compatible = "renesas,r8a77965-thermal",
.data = &rcar_gen3_ths_tj_1,
.data = &rcar_gen3_thermal_info,
},
{
.compatible = "renesas,r8a77980-thermal",
.data = &rcar_gen3_ths_tj_1,
.data = &rcar_gen3_thermal_info,
},
{
.compatible = "renesas,r8a779a0-thermal",
.data = &rcar_gen3_ths_tj_1,
.data = &rcar_gen3_thermal_info,
},
{
.compatible = "renesas,r8a779f0-thermal",
.data = &rcar_gen3_ths_tj_1,
.data = &rcar_gen4_thermal_info,
},
{
.compatible = "renesas,r8a779g0-thermal",
.data = &rcar_gen3_ths_tj_1,
.data = &rcar_gen4_thermal_info,
},
{},
};
......@@ -418,7 +481,6 @@ static int rcar_gen3_thermal_probe(struct platform_device *pdev)
{
struct rcar_gen3_thermal_priv *priv;
struct device *dev = &pdev->dev;
const int *ths_tj_1 = of_device_get_match_data(dev);
struct resource *res;
struct thermal_zone_device *zone;
unsigned int i;
......@@ -430,6 +492,7 @@ static int rcar_gen3_thermal_probe(struct platform_device *pdev)
priv->ops = rcar_gen3_tz_of_ops;
priv->info = of_device_get_match_data(dev);
platform_set_drvdata(pdev, priv);
if (rcar_gen3_thermal_request_irqs(priv, pdev))
......@@ -469,7 +532,7 @@ static int rcar_gen3_thermal_probe(struct platform_device *pdev)
struct rcar_gen3_thermal_tsc *tsc = priv->tscs[i];
rcar_gen3_thermal_init(priv, tsc);
rcar_gen3_thermal_calc_coefs(priv, tsc, *ths_tj_1);
rcar_gen3_thermal_calc_coefs(priv, tsc, priv->info->ths_tj_1);
zone = devm_thermal_of_zone_register(dev, i, tsc, &priv->ops);
if (IS_ERR(zone)) {
......
......@@ -227,14 +227,12 @@ int st_thermal_register(struct platform_device *pdev,
}
EXPORT_SYMBOL_GPL(st_thermal_register);
int st_thermal_unregister(struct platform_device *pdev)
void st_thermal_unregister(struct platform_device *pdev)
{
struct st_thermal_sensor *sensor = platform_get_drvdata(pdev);
st_thermal_sensor_off(sensor);
thermal_zone_device_unregister(sensor->thermal_dev);
return 0;
}
EXPORT_SYMBOL_GPL(st_thermal_unregister);
......
......@@ -94,7 +94,7 @@ struct st_thermal_sensor {
extern int st_thermal_register(struct platform_device *pdev,
const struct of_device_id *st_thermal_of_match);
extern int st_thermal_unregister(struct platform_device *pdev);
extern void st_thermal_unregister(struct platform_device *pdev);
extern const struct dev_pm_ops st_thermal_pm_ops;
#endif /* __STI_RESET_SYSCFG_H */
......@@ -172,9 +172,9 @@ static int st_mmap_probe(struct platform_device *pdev)
return st_thermal_register(pdev, st_mmap_thermal_of_match);
}
static int st_mmap_remove(struct platform_device *pdev)
static void st_mmap_remove(struct platform_device *pdev)
{
return st_thermal_unregister(pdev);
st_thermal_unregister(pdev);
}
static struct platform_driver st_mmap_thermal_driver = {
......@@ -184,7 +184,7 @@ static struct platform_driver st_mmap_thermal_driver = {
.of_match_table = st_mmap_thermal_of_match,
},
.probe = st_mmap_probe,
.remove = st_mmap_remove,
.remove_new = st_mmap_remove,
};
module_platform_driver(st_mmap_thermal_driver);
......
......@@ -319,6 +319,11 @@ static int sun8i_ths_calibrate(struct ths_device *tmdev)
return ret;
}
static void sun8i_ths_reset_control_assert(void *data)
{
reset_control_assert(data);
}
static int sun8i_ths_resource_init(struct ths_device *tmdev)
{
struct device *dev = tmdev->dev;
......@@ -339,47 +344,35 @@ static int sun8i_ths_resource_init(struct ths_device *tmdev)
if (IS_ERR(tmdev->reset))
return PTR_ERR(tmdev->reset);
tmdev->bus_clk = devm_clk_get(&pdev->dev, "bus");
ret = reset_control_deassert(tmdev->reset);
if (ret)
return ret;
ret = devm_add_action_or_reset(dev, sun8i_ths_reset_control_assert,
tmdev->reset);
if (ret)
return ret;
tmdev->bus_clk = devm_clk_get_enabled(&pdev->dev, "bus");
if (IS_ERR(tmdev->bus_clk))
return PTR_ERR(tmdev->bus_clk);
}
if (tmdev->chip->has_mod_clk) {
tmdev->mod_clk = devm_clk_get(&pdev->dev, "mod");
tmdev->mod_clk = devm_clk_get_enabled(&pdev->dev, "mod");
if (IS_ERR(tmdev->mod_clk))
return PTR_ERR(tmdev->mod_clk);
}
ret = reset_control_deassert(tmdev->reset);
if (ret)
return ret;
ret = clk_prepare_enable(tmdev->bus_clk);
if (ret)
goto assert_reset;
ret = clk_set_rate(tmdev->mod_clk, 24000000);
if (ret)
goto bus_disable;
ret = clk_prepare_enable(tmdev->mod_clk);
if (ret)
goto bus_disable;
return ret;
ret = sun8i_ths_calibrate(tmdev);
if (ret)
goto mod_disable;
return ret;
return 0;
mod_disable:
clk_disable_unprepare(tmdev->mod_clk);
bus_disable:
clk_disable_unprepare(tmdev->bus_clk);
assert_reset:
reset_control_assert(tmdev->reset);
return ret;
}
static int sun8i_h3_thermal_init(struct ths_device *tmdev)
......@@ -475,9 +468,7 @@ static int sun8i_ths_register(struct ths_device *tmdev)
if (IS_ERR(tmdev->sensor[i].tzd))
return PTR_ERR(tmdev->sensor[i].tzd);
if (devm_thermal_add_hwmon_sysfs(tmdev->dev, tmdev->sensor[i].tzd))
dev_warn(tmdev->dev,
"Failed to add hwmon sysfs attributes\n");
devm_thermal_add_hwmon_sysfs(tmdev->dev, tmdev->sensor[i].tzd);
}
return 0;
......@@ -530,17 +521,6 @@ static int sun8i_ths_probe(struct platform_device *pdev)
return 0;
}
static int sun8i_ths_remove(struct platform_device *pdev)
{
struct ths_device *tmdev = platform_get_drvdata(pdev);
clk_disable_unprepare(tmdev->mod_clk);
clk_disable_unprepare(tmdev->bus_clk);
reset_control_assert(tmdev->reset);
return 0;
}
static const struct ths_thermal_chip sun8i_a83t_ths = {
.sensor_num = 3,
.scale = 705,
......@@ -642,7 +622,6 @@ MODULE_DEVICE_TABLE(of, of_ths_match);
static struct platform_driver ths_driver = {
.probe = sun8i_ths_probe,
.remove = sun8i_ths_remove,
.driver = {
.name = "sun8i-thermal",
.of_match_table = of_ths_match,
......
......@@ -523,8 +523,7 @@ static int tegra_tsensor_register_channel(struct tegra_tsensor *ts,
return 0;
}
if (devm_thermal_add_hwmon_sysfs(ts->dev, tsc->tzd))
dev_warn(ts->dev, "failed to add hwmon sysfs attributes\n");
devm_thermal_add_hwmon_sysfs(ts->dev, tsc->tzd);
return 0;
}
......
......@@ -13,6 +13,8 @@
#include <linux/slab.h>
#include <linux/thermal.h>
#include "thermal_hwmon.h"
struct gadc_thermal_info {
struct device *dev;
struct thermal_zone_device *tz_dev;
......@@ -153,6 +155,8 @@ static int gadc_thermal_probe(struct platform_device *pdev)
return ret;
}
devm_thermal_add_hwmon_sysfs(&pdev->dev, gti->tz_dev);
return 0;
}
......
......@@ -23,6 +23,8 @@
#define DEFAULT_THERMAL_GOVERNOR "user_space"
#elif defined(CONFIG_THERMAL_DEFAULT_GOV_POWER_ALLOCATOR)
#define DEFAULT_THERMAL_GOVERNOR "power_allocator"
#elif defined(CONFIG_THERMAL_DEFAULT_GOV_BANG_BANG)
#define DEFAULT_THERMAL_GOVERNOR "bang_bang"
#endif
/* Initial state of a cooling device during binding */
......
......@@ -271,11 +271,14 @@ int devm_thermal_add_hwmon_sysfs(struct device *dev, struct thermal_zone_device
ptr = devres_alloc(devm_thermal_hwmon_release, sizeof(*ptr),
GFP_KERNEL);
if (!ptr)
if (!ptr) {
dev_warn(dev, "Failed to allocate device resource data\n");
return -ENOMEM;
}
ret = thermal_add_hwmon_sysfs(tz);
if (ret) {
dev_warn(dev, "Failed to add hwmon sysfs attributes\n");
devres_free(ptr);
return ret;
}
......
......@@ -182,8 +182,7 @@ int ti_thermal_expose_sensor(struct ti_bandgap *bgp, int id,
ti_bandgap_write_update_interval(bgp, data->sensor_id,
TI_BANDGAP_UPDATE_INTERVAL_MS);
if (devm_thermal_add_hwmon_sysfs(bgp->dev, data->ti_thermal))
dev_warn(bgp->dev, "failed to add hwmon sysfs attributes\n");
devm_thermal_add_hwmon_sysfs(bgp->dev, data->ti_thermal);
return 0;
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment