Skip to content

Commit

Permalink
Merge tag 'thermal-5.17-rc1' of git://git.kernel.org/pub/scm/linux/ke…
Browse files Browse the repository at this point in the history
…rnel/git/rafael/linux-pm

Pull thermal control updates from Rafael Wysocki:
 "These add a new driver for Renesas RZ/G2L TSU, update a few existing
  thermal control drivers and clean up the tmon utility.

  Specifics:

   - Add new TSU driver and DT bindings for the Renesas RZ/G2L platform
     (Biju Das).

   - Fix missing check when calling reset_control_deassert() in the
     rz2gl thermal driver (Biju Das).

   - In preparation for FORTIFY_SOURCE performing compile-time and
     run-time field bounds checking for memcpy(), avoid intentionally
     writing across neighboring fields in the int340x thermal control
     driver (Kees Cook).

   - Fix RFIM mailbox write commands handling in the int340x thermal
     control driver (Sumeet Pawnikar).

   - Fix PM issue occurring in the iMX thermal control driver during
     suspend/resume by implementing PM runtime support in it (Oleksij
     Rempel).

   - Add 'const' annotation to thermal_cooling_ops in the Intel
     powerclamp driver (Rikard Falkeborn).

   - Fix missing ADC bit set in the iMX8MP thermal driver to enable the
     sensor (Paul Gerber).

   - Drop unused local variable definition from tmon (ran jianping)"

* tag 'thermal-5.17-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm:
  thermal/drivers/int340x: Fix RFIM mailbox write commands
  thermal/drivers/rz2gl: Add error check for reset_control_deassert()
  thermal/drivers/imx8mm: Enable ADC when enabling monitor
  thermal/drivers: Add TSU driver for RZ/G2L
  dt-bindings: thermal: Document Renesas RZ/G2L TSU
  thermal/drivers/intel_powerclamp: Constify static thermal_cooling_device_ops
  thermal/drivers/imx: Implement runtime PM support
  thermal: tools: tmon: remove unneeded local variable
  thermal: int340x: Use struct_group() for memcpy() region
  • Loading branch information
torvalds committed Jan 11, 2022
2 parents b35b6d4 + fff489f commit fe2437c
Show file tree
Hide file tree
Showing 13 changed files with 526 additions and 134 deletions.
76 changes: 76 additions & 0 deletions Documentation/devicetree/bindings/thermal/rzg2l-thermal.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/thermal/rzg2l-thermal.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#

title: Renesas RZ/G2L Thermal Sensor Unit

description:
On RZ/G2L SoCs, the thermal sensor unit (TSU) measures the
temperature(Tj) inside the LSI.

maintainers:
- Biju Das <[email protected]>

properties:
compatible:
items:
- enum:
- renesas,r9a07g044-tsu # RZ/G2{L,LC}
- const: renesas,rzg2l-tsu

reg:
maxItems: 1

clocks:
maxItems: 1

power-domains:
maxItems: 1

resets:
maxItems: 1

"#thermal-sensor-cells":
const: 1

required:
- compatible
- reg
- clocks
- power-domains
- resets
- "#thermal-sensor-cells"

additionalProperties: false

examples:
- |
#include <dt-bindings/clock/r9a07g044-cpg.h>
tsu: thermal@10059400 {
compatible = "renesas,r9a07g044-tsu",
"renesas,rzg2l-tsu";
reg = <0x10059400 0x400>;
clocks = <&cpg CPG_MOD R9A07G044_TSU_PCLK>;
resets = <&cpg R9A07G044_TSU_PRESETN>;
power-domains = <&cpg>;
#thermal-sensor-cells = <1>;
};
thermal-zones {
cpu-thermal {
polling-delay-passive = <250>;
polling-delay = <1000>;
thermal-sensors = <&tsu 0>;
trips {
sensor_crit: sensor-crit {
temperature = <125000>;
hysteresis = <1000>;
type = "critical";
};
};
};
};
9 changes: 9 additions & 0 deletions drivers/thermal/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -354,6 +354,15 @@ config RCAR_GEN3_THERMAL
Enable this to plug the R-Car Gen3 or RZ/G2 thermal sensor driver into
the Linux thermal framework.

config RZG2L_THERMAL
tristate "Renesas RZ/G2L thermal driver"
depends on ARCH_RENESAS || COMPILE_TEST
depends on HAS_IOMEM
depends on OF
help
Enable this to plug the RZ/G2L thermal sensor driver into the Linux
thermal framework.

config KIRKWOOD_THERMAL
tristate "Temperature sensor on Marvell Kirkwood SoCs"
depends on MACH_KIRKWOOD || COMPILE_TEST
Expand Down
1 change: 1 addition & 0 deletions drivers/thermal/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ obj-$(CONFIG_SUN8I_THERMAL) += sun8i_thermal.o
obj-$(CONFIG_ROCKCHIP_THERMAL) += rockchip_thermal.o
obj-$(CONFIG_RCAR_THERMAL) += rcar_thermal.o
obj-$(CONFIG_RCAR_GEN3_THERMAL) += rcar_gen3_thermal.o
obj-$(CONFIG_RZG2L_THERMAL) += rzg2l_thermal.o
obj-$(CONFIG_KIRKWOOD_THERMAL) += kirkwood_thermal.o
obj-y += samsung/
obj-$(CONFIG_DOVE_THERMAL) += dove_thermal.o
Expand Down
3 changes: 3 additions & 0 deletions drivers/thermal/imx8mm_thermal.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
#define TPS 0x4
#define TRITSR 0x20 /* TMU immediate temp */

#define TER_ADC_PD BIT(30)
#define TER_EN BIT(31)
#define TRITSR_TEMP0_VAL_MASK 0xff
#define TRITSR_TEMP1_VAL_MASK 0xff0000
Expand Down Expand Up @@ -113,6 +114,8 @@ static void imx8mm_tmu_enable(struct imx8mm_tmu *tmu, bool enable)

val = readl_relaxed(tmu->base + TER);
val = enable ? (val | TER_EN) : (val & ~TER_EN);
if (tmu->socdata->version == TMU_VER2)
val = enable ? (val & ~TER_ADC_PD) : (val | TER_ADC_PD);
writel_relaxed(val, tmu->base + TER);
}

Expand Down
145 changes: 91 additions & 54 deletions drivers/thermal/imx_thermal.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
#include <linux/regmap.h>
#include <linux/thermal.h>
#include <linux/nvmem-consumer.h>
#include <linux/pm_runtime.h>

#define REG_SET 0x4
#define REG_CLR 0x8
Expand Down Expand Up @@ -194,6 +195,7 @@ static struct thermal_soc_data thermal_imx7d_data = {
};

struct imx_thermal_data {
struct device *dev;
struct cpufreq_policy *policy;
struct thermal_zone_device *tz;
struct thermal_cooling_device *cdev;
Expand Down Expand Up @@ -252,44 +254,15 @@ static int imx_get_temp(struct thermal_zone_device *tz, int *temp)
const struct thermal_soc_data *soc_data = data->socdata;
struct regmap *map = data->tempmon;
unsigned int n_meas;
bool wait, run_measurement;
u32 val;
int ret;

run_measurement = !data->irq_enabled;
if (!run_measurement) {
/* Check if a measurement is currently in progress */
regmap_read(map, soc_data->temp_data, &val);
wait = !(val & soc_data->temp_valid_mask);
} else {
/*
* Every time we measure the temperature, we will power on the
* temperature sensor, enable measurements, take a reading,
* disable measurements, power off the temperature sensor.
*/
regmap_write(map, soc_data->sensor_ctrl + REG_CLR,
soc_data->power_down_mask);
regmap_write(map, soc_data->sensor_ctrl + REG_SET,
soc_data->measure_temp_mask);

wait = true;
}

/*
* According to the temp sensor designers, it may require up to ~17us
* to complete a measurement.
*/
if (wait)
usleep_range(20, 50);
ret = pm_runtime_resume_and_get(data->dev);
if (ret < 0)
return ret;

regmap_read(map, soc_data->temp_data, &val);

if (run_measurement) {
regmap_write(map, soc_data->sensor_ctrl + REG_CLR,
soc_data->measure_temp_mask);
regmap_write(map, soc_data->sensor_ctrl + REG_SET,
soc_data->power_down_mask);
}

if ((val & soc_data->temp_valid_mask) == 0) {
dev_dbg(&tz->device, "temp measurement never finished\n");
return -EAGAIN;
Expand Down Expand Up @@ -328,31 +301,25 @@ static int imx_get_temp(struct thermal_zone_device *tz, int *temp)
enable_irq(data->irq);
}

pm_runtime_put(data->dev);

return 0;
}

static int imx_change_mode(struct thermal_zone_device *tz,
enum thermal_device_mode mode)
{
struct imx_thermal_data *data = tz->devdata;
struct regmap *map = data->tempmon;
const struct thermal_soc_data *soc_data = data->socdata;

if (mode == THERMAL_DEVICE_ENABLED) {
regmap_write(map, soc_data->sensor_ctrl + REG_CLR,
soc_data->power_down_mask);
regmap_write(map, soc_data->sensor_ctrl + REG_SET,
soc_data->measure_temp_mask);
pm_runtime_get(data->dev);

if (!data->irq_enabled) {
data->irq_enabled = true;
enable_irq(data->irq);
}
} else {
regmap_write(map, soc_data->sensor_ctrl + REG_CLR,
soc_data->measure_temp_mask);
regmap_write(map, soc_data->sensor_ctrl + REG_SET,
soc_data->power_down_mask);
pm_runtime_put(data->dev);

if (data->irq_enabled) {
disable_irq(data->irq);
Expand Down Expand Up @@ -393,6 +360,11 @@ static int imx_set_trip_temp(struct thermal_zone_device *tz, int trip,
int temp)
{
struct imx_thermal_data *data = tz->devdata;
int ret;

ret = pm_runtime_resume_and_get(data->dev);
if (ret < 0)
return ret;

/* do not allow changing critical threshold */
if (trip == IMX_TRIP_CRITICAL)
Expand All @@ -406,6 +378,8 @@ static int imx_set_trip_temp(struct thermal_zone_device *tz, int trip,

imx_set_alarm_temp(data, temp);

pm_runtime_put(data->dev);

return 0;
}

Expand Down Expand Up @@ -681,6 +655,8 @@ static int imx_thermal_probe(struct platform_device *pdev)
if (!data)
return -ENOMEM;

data->dev = &pdev->dev;

map = syscon_regmap_lookup_by_phandle(pdev->dev.of_node, "fsl,tempmon");
if (IS_ERR(map)) {
ret = PTR_ERR(map);
Expand Down Expand Up @@ -800,6 +776,16 @@ static int imx_thermal_probe(struct platform_device *pdev)
data->socdata->power_down_mask);
regmap_write(map, data->socdata->sensor_ctrl + REG_SET,
data->socdata->measure_temp_mask);
/* After power up, we need a delay before first access can be done. */
usleep_range(20, 50);

/* the core was configured and enabled just before */
pm_runtime_set_active(&pdev->dev);
pm_runtime_enable(data->dev);

ret = pm_runtime_resume_and_get(data->dev);
if (ret < 0)
goto disable_runtime_pm;

data->irq_enabled = true;
ret = thermal_zone_device_enable(data->tz);
Expand All @@ -814,10 +800,15 @@ static int imx_thermal_probe(struct platform_device *pdev)
goto thermal_zone_unregister;
}

pm_runtime_put(data->dev);

return 0;

thermal_zone_unregister:
thermal_zone_device_unregister(data->tz);
disable_runtime_pm:
pm_runtime_put_noidle(data->dev);
pm_runtime_disable(data->dev);
clk_disable:
clk_disable_unprepare(data->thermal_clk);
legacy_cleanup:
Expand All @@ -829,13 +820,9 @@ static int imx_thermal_probe(struct platform_device *pdev)
static int imx_thermal_remove(struct platform_device *pdev)
{
struct imx_thermal_data *data = platform_get_drvdata(pdev);
struct regmap *map = data->tempmon;

/* Disable measurements */
regmap_write(map, data->socdata->sensor_ctrl + REG_SET,
data->socdata->power_down_mask);
if (!IS_ERR(data->thermal_clk))
clk_disable_unprepare(data->thermal_clk);
pm_runtime_put_noidle(data->dev);
pm_runtime_disable(data->dev);

thermal_zone_device_unregister(data->tz);
imx_thermal_unregister_legacy_cooling(data);
Expand All @@ -858,29 +845,79 @@ static int __maybe_unused imx_thermal_suspend(struct device *dev)
ret = thermal_zone_device_disable(data->tz);
if (ret)
return ret;

return pm_runtime_force_suspend(data->dev);
}

static int __maybe_unused imx_thermal_resume(struct device *dev)
{
struct imx_thermal_data *data = dev_get_drvdata(dev);
int ret;

ret = pm_runtime_force_resume(data->dev);
if (ret)
return ret;
/* Enabled thermal sensor after resume */
return thermal_zone_device_enable(data->tz);
}

static int __maybe_unused imx_thermal_runtime_suspend(struct device *dev)
{
struct imx_thermal_data *data = dev_get_drvdata(dev);
const struct thermal_soc_data *socdata = data->socdata;
struct regmap *map = data->tempmon;
int ret;

ret = regmap_write(map, socdata->sensor_ctrl + REG_CLR,
socdata->measure_temp_mask);
if (ret)
return ret;

ret = regmap_write(map, socdata->sensor_ctrl + REG_SET,
socdata->power_down_mask);
if (ret)
return ret;

clk_disable_unprepare(data->thermal_clk);

return 0;
}

static int __maybe_unused imx_thermal_resume(struct device *dev)
static int __maybe_unused imx_thermal_runtime_resume(struct device *dev)
{
struct imx_thermal_data *data = dev_get_drvdata(dev);
const struct thermal_soc_data *socdata = data->socdata;
struct regmap *map = data->tempmon;
int ret;

ret = clk_prepare_enable(data->thermal_clk);
if (ret)
return ret;
/* Enabled thermal sensor after resume */
ret = thermal_zone_device_enable(data->tz);

ret = regmap_write(map, socdata->sensor_ctrl + REG_CLR,
socdata->power_down_mask);
if (ret)
return ret;

ret = regmap_write(map, socdata->sensor_ctrl + REG_SET,
socdata->measure_temp_mask);
if (ret)
return ret;

/*
* According to the temp sensor designers, it may require up to ~17us
* to complete a measurement.
*/
usleep_range(20, 50);

return 0;
}

static SIMPLE_DEV_PM_OPS(imx_thermal_pm_ops,
imx_thermal_suspend, imx_thermal_resume);
static const struct dev_pm_ops imx_thermal_pm_ops = {
SET_SYSTEM_SLEEP_PM_OPS(imx_thermal_suspend, imx_thermal_resume)
SET_RUNTIME_PM_OPS(imx_thermal_runtime_suspend,
imx_thermal_runtime_resume, NULL)
};

static struct platform_driver imx_thermal = {
.driver = {
Expand Down
5 changes: 3 additions & 2 deletions drivers/thermal/intel/int340x_thermal/acpi_thermal_rel.c
Original file line number Diff line number Diff line change
Expand Up @@ -250,8 +250,9 @@ static int fill_art(char __user *ubuf)
get_single_name(arts[i].source, art_user[i].source_device);
get_single_name(arts[i].target, art_user[i].target_device);
/* copy the rest int data in addition to source and target */
memcpy(&art_user[i].weight, &arts[i].weight,
sizeof(u64) * (ACPI_NR_ART_ELEMENTS - 2));
BUILD_BUG_ON(sizeof(art_user[i].data) !=
sizeof(u64) * (ACPI_NR_ART_ELEMENTS - 2));
memcpy(&art_user[i].data, &arts[i].data, sizeof(art_user[i].data));
}

if (copy_to_user(ubuf, art_user, art_len))
Expand Down
Loading

0 comments on commit fe2437c

Please sign in to comment.