Skip to content

Commit

Permalink
Merge branch 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/…
Browse files Browse the repository at this point in the history
…rzhang/linux

Pull thermal updates from Zhang Rui:

 - fix resources release in error paths when registering thermal zone.
   (Christophe Jaillet)

 - introduce a new thermal driver for on-chip PVT (Process, Voltage and
   Temperature) monitoring unit implemented on UniPhier SoCs. This
   driver supports temperature monitoring and alert function. (Kunihiko
   Hayashi)

 - Add support for mt2712 chip in the mtk_thermal driver. (Louis Yu)

 - Add support for RK3328 SOC in rockchip_thermal driver. (Rocky Hao)

 - cleanup a couple of platform thermal drivers to constify
   thermal_zone_of_device_ops structures. (Julia Lawall)

 - a couple of fixes in int340x and intel_pch_thermal thermal driver.
   (Arvind Yadav, Sumeet Pawnikar, Brian Bian, Ed Swierk, Zhang Rui)

* 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/rzhang/linux: (27 commits)
  Thermal: int3406_thermal: fix thermal sysfs I/F
  thermal: mediatek: minor mtk_thermal.c cleanups
  thermal: mediatek: extend calibration data for mt2712 chip
  thermal: mediatek: add Mediatek thermal driver for mt2712
  dt-bindings: thermal: Add binding document for Mediatek thermal controller
  thermal: intel_pch_thermal: Fix enable check on Broadwell-DE
  thermal: rockchip: Support the RK3328 SOC in thermal driver
  dt-bindings: rockchip-thermal: Support the RK3328 SoC compatible
  thermal: bcm2835: constify thermal_zone_of_device_ops structures
  thermal: exynos: constify thermal_zone_of_device_ops structures
  thermal: zx2967: constify thermal_zone_of_device_ops structures
  thermal: rcar_gen3_thermal: constify thermal_zone_of_device_ops structures
  thermal: qoriq: constify thermal_zone_of_device_ops structures
  thermal: hisilicon: constify thermal_zone_of_device_ops structures
  thermal: core: Fix resources release in error paths in thermal_zone_device_register()
  thermal: core: Use the new 'thermal_zone_destroy_device_groups()' helper function
  thermal: core: Add some new helper functions to free resources
  thermal: int3400_thermal: process "thermal table changed" event
  thermal: uniphier: add UniPhier thermal driver
  dt-bindings: thermal: add binding documentation for UniPhier thermal monitor
  ...
  • Loading branch information
torvalds committed Sep 12, 2017
2 parents 8e7757d + b32b5e1 commit c971aa3
Show file tree
Hide file tree
Showing 24 changed files with 747 additions and 106 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ Required properties:
- compatible:
- "mediatek,mt8173-thermal" : For MT8173 family of SoCs
- "mediatek,mt2701-thermal" : For MT2701 family of SoCs
- "mediatek,mt2712-thermal" : For MT2712 family of SoCs
- reg: Address range of the thermal controller
- interrupts: IRQ for the thermal controller
- clocks, clock-names: Clocks needed for the thermal controller. required
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ Required properties:
- compatible : should be "rockchip,<name>-tsadc"
"rockchip,rk3228-tsadc": found on RK3228 SoCs
"rockchip,rk3288-tsadc": found on RK3288 SoCs
"rockchip,rk3328-tsadc": found on RK3328 SoCs
"rockchip,rk3368-tsadc": found on RK3368 SoCs
"rockchip,rk3399-tsadc": found on RK3399 SoCs
- reg : physical base address of the controller and length of memory mapped
Expand Down
64 changes: 64 additions & 0 deletions Documentation/devicetree/bindings/thermal/uniphier-thermal.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
* UniPhier Thermal bindings

This describes the devicetree bindings for thermal monitor supported by
PVT(Process, Voltage and Temperature) monitoring unit implemented on Socionext
UniPhier SoCs.

Required properties:
- compatible :
- "socionext,uniphier-pxs2-thermal" : For UniPhier PXs2 SoC
- "socionext,uniphier-ld20-thermal" : For UniPhier LD20 SoC
- interrupts : IRQ for the temperature alarm
- #thermal-sensor-cells : Should be 0. See ./thermal.txt for details.

Optional properties:
- socionext,tmod-calibration: A pair of calibrated values referred from PVT,
in case that the values aren't set on SoC,
like a reference board.

Example:

sysctrl@61840000 {
compatible = "socionext,uniphier-ld20-sysctrl",
"simple-mfd", "syscon";
reg = <0x61840000 0x10000>;
...
pvtctl: pvtctl {
compatible = "socionext,uniphier-ld20-thermal";
interrupts = <0 3 1>;
#thermal-sensor-cells = <0>;
};
...
};

thermal-zones {
cpu_thermal {
polling-delay-passive = <250>; /* 250ms */
polling-delay = <1000>; /* 1000ms */
thermal-sensors = <&pvtctl>;

trips {
cpu_crit: cpu_crit {
temperature = <110000>; /* 110C */
hysteresis = <2000>;
type = "critical";
};
cpu_alert: cpu_alert {
temperature = <100000>; /* 100C */
hysteresis = <2000>;
type = "passive";
};
};

cooling-maps {
map0 {
trip = <&cpu_alert>;
cooling-device = <&cpu0 (-1) (-1)>;
};
map1 {
trip = <&cpu_alert>;
cooling-device = <&cpu2 (-1) (-1)>;
};
};
};
};
12 changes: 10 additions & 2 deletions drivers/thermal/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -342,7 +342,7 @@ config X86_PKG_TEMP_THERMAL

config INTEL_SOC_DTS_IOSF_CORE
tristate
depends on X86
depends on X86 && PCI
select IOSF_MBI
help
This is becoming a common feature for Intel SoCs to expose the additional
Expand All @@ -352,7 +352,7 @@ config INTEL_SOC_DTS_IOSF_CORE

config INTEL_SOC_DTS_THERMAL
tristate "Intel SoCs DTS thermal driver"
depends on X86
depends on X86 && PCI
select INTEL_SOC_DTS_IOSF_CORE
select THERMAL_WRITABLE_TRIPS
help
Expand Down Expand Up @@ -473,4 +473,12 @@ config ZX2967_THERMAL
the primitive temperature sensor embedded in zx2967 SoCs.
This sensor generates the real time die temperature.

config UNIPHIER_THERMAL
tristate "Socionext UniPhier thermal driver"
depends on ARCH_UNIPHIER || COMPILE_TEST
depends on THERMAL_OF && MFD_SYSCON
help
Enable this to plug in UniPhier on-chip PVT thermal driver into the
thermal framework. The driver supports CPU thermal zone temperature
reporting and a couple of trip points.
endif
1 change: 1 addition & 0 deletions drivers/thermal/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -59,3 +59,4 @@ obj-$(CONFIG_HISI_THERMAL) += hisi_thermal.o
obj-$(CONFIG_MTK_THERMAL) += mtk_thermal.o
obj-$(CONFIG_GENERIC_ADC_THERMAL) += thermal-generic-adc.o
obj-$(CONFIG_ZX2967_THERMAL) += zx2967_thermal.o
obj-$(CONFIG_UNIPHIER_THERMAL) += uniphier_thermal.o
2 changes: 1 addition & 1 deletion drivers/thermal/broadcom/bcm2835_thermal.c
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ static void bcm2835_thermal_debugfs(struct platform_device *pdev)
debugfs_create_regset32("regset", 0444, data->debugfsdir, regset);
}

static struct thermal_zone_of_device_ops bcm2835_thermal_ops = {
static const struct thermal_zone_of_device_ops bcm2835_thermal_ops = {
.get_temp = bcm2835_thermal_get_temp,
};

Expand Down
2 changes: 1 addition & 1 deletion drivers/thermal/hisi_thermal.c
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,7 @@ static int hisi_thermal_get_temp(void *_sensor, int *temp)
return 0;
}

static struct thermal_zone_of_device_ops hisi_of_thermal_ops = {
static const struct thermal_zone_of_device_ops hisi_of_thermal_ops = {
.get_temp = hisi_thermal_get_temp,
};

Expand Down
2 changes: 1 addition & 1 deletion drivers/thermal/int340x_thermal/acpi_thermal_rel.c
Original file line number Diff line number Diff line change
Expand Up @@ -228,7 +228,7 @@ static void get_single_name(acpi_handle handle, char *name)
struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER};

if (ACPI_FAILURE(acpi_get_name(handle, ACPI_SINGLE_NAME, &buffer)))
pr_warn("Failed get name from handle\n");
pr_warn("Failed to get device name from acpi handle\n");
else {
memcpy(name, buffer.pointer, ACPI_NAME_SIZE);
kfree(buffer.pointer);
Expand Down
8 changes: 4 additions & 4 deletions drivers/thermal/int340x_thermal/acpi_thermal_rel.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,10 +34,10 @@ struct trt {
acpi_handle target;
u64 influence;
u64 sample_period;
u64 reverved1;
u64 reverved2;
u64 reverved3;
u64 reverved4;
u64 reserved1;
u64 reserved2;
u64 reserved3;
u64 reserved4;
} __packed;

#define ACPI_NR_ART_ELEMENTS 13
Expand Down
43 changes: 42 additions & 1 deletion drivers/thermal/int340x_thermal/int3400_thermal.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@
#include <linux/thermal.h>
#include "acpi_thermal_rel.h"

#define INT3400_THERMAL_TABLE_CHANGED 0x83

enum int3400_thermal_uuid {
INT3400_THERMAL_PASSIVE_1,
INT3400_THERMAL_ACTIVE,
Expand Down Expand Up @@ -104,7 +106,7 @@ static struct attribute *uuid_attrs[] = {
NULL
};

static struct attribute_group uuid_attribute_group = {
static const struct attribute_group uuid_attribute_group = {
.attrs = uuid_attrs,
.name = "uuids"
};
Expand Down Expand Up @@ -185,6 +187,35 @@ static int int3400_thermal_run_osc(acpi_handle handle,
return result;
}

static void int3400_notify(acpi_handle handle,
u32 event,
void *data)
{
struct int3400_thermal_priv *priv = data;
char *thermal_prop[5];

if (!priv)
return;

switch (event) {
case INT3400_THERMAL_TABLE_CHANGED:
thermal_prop[0] = kasprintf(GFP_KERNEL, "NAME=%s",
priv->thermal->type);
thermal_prop[1] = kasprintf(GFP_KERNEL, "TEMP=%d",
priv->thermal->temperature);
thermal_prop[2] = kasprintf(GFP_KERNEL, "TRIP=");
thermal_prop[3] = kasprintf(GFP_KERNEL, "EVENT=%d",
THERMAL_TABLE_CHANGED);
thermal_prop[4] = NULL;
kobject_uevent_env(&priv->thermal->device.kobj, KOBJ_CHANGE,
thermal_prop);
break;
default:
dev_err(&priv->adev->dev, "Unsupported event [0x%x]\n", event);
break;
}
}

static int int3400_thermal_get_temp(struct thermal_zone_device *thermal,
int *temp)
{
Expand Down Expand Up @@ -290,6 +321,12 @@ static int int3400_thermal_probe(struct platform_device *pdev)
if (result)
goto free_zone;

result = acpi_install_notify_handler(
priv->adev->handle, ACPI_DEVICE_NOTIFY, int3400_notify,
(void *)priv);
if (result)
goto free_zone;

return 0;

free_zone:
Expand All @@ -306,6 +343,10 @@ static int int3400_thermal_remove(struct platform_device *pdev)
{
struct int3400_thermal_priv *priv = platform_get_drvdata(pdev);

acpi_remove_notify_handler(
priv->adev->handle, ACPI_DEVICE_NOTIFY,
int3400_notify);

if (!priv->rel_misc_dev_res)
acpi_thermal_rel_misc_device_remove(priv->adev->handle);

Expand Down
96 changes: 37 additions & 59 deletions drivers/thermal/int340x_thermal/int3406_thermal.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,39 +21,33 @@

struct int3406_thermal_data {
int upper_limit;
int upper_limit_index;
int lower_limit;
int lower_limit_index;
acpi_handle handle;
struct acpi_video_device_brightness *br;
struct backlight_device *raw_bd;
struct thermal_cooling_device *cooling_dev;
};

static int int3406_thermal_to_raw(int level, struct int3406_thermal_data *d)
{
int max_level = d->br->levels[d->br->count - 1];
int raw_max = d->raw_bd->props.max_brightness;

return level * raw_max / max_level;
}

static int int3406_thermal_to_acpi(int level, struct int3406_thermal_data *d)
{
int raw_max = d->raw_bd->props.max_brightness;
int max_level = d->br->levels[d->br->count - 1];

return level * max_level / raw_max;
}
/*
* According to the ACPI spec,
* "Each brightness level is represented by a number between 0 and 100,
* and can be thought of as a percentage. For example, 50 can be 50%
* power consumption or 50% brightness, as defined by the OEM."
*
* As int3406 device uses this value to communicate with the native
* graphics driver, we make the assumption that it represents
* the percentage of brightness only
*/
#define ACPI_TO_RAW(v, d) (d->raw_bd->props.max_brightness * v / 100)
#define RAW_TO_ACPI(v, d) (v * 100 / d->raw_bd->props.max_brightness)

static int
int3406_thermal_get_max_state(struct thermal_cooling_device *cooling_dev,
unsigned long *state)
{
struct int3406_thermal_data *d = cooling_dev->devdata;
int index = d->lower_limit_index ? d->lower_limit_index : 2;

*state = d->br->count - 1 - index;
*state = d->upper_limit - d->lower_limit;
return 0;
}

Expand All @@ -62,19 +56,15 @@ int3406_thermal_set_cur_state(struct thermal_cooling_device *cooling_dev,
unsigned long state)
{
struct int3406_thermal_data *d = cooling_dev->devdata;
int level, raw_level;
int acpi_level, raw_level;

if (state > d->br->count - 3)
if (state > d->upper_limit - d->lower_limit)
return -EINVAL;

state = d->br->count - 1 - state;
level = d->br->levels[state];
acpi_level = d->br->levels[d->upper_limit - state];

if ((d->upper_limit && level > d->upper_limit) ||
(d->lower_limit && level < d->lower_limit))
return -EINVAL;
raw_level = ACPI_TO_RAW(acpi_level, d);

raw_level = int3406_thermal_to_raw(level, d);
return backlight_device_set_brightness(d->raw_bd, raw_level);
}

Expand All @@ -83,27 +73,22 @@ int3406_thermal_get_cur_state(struct thermal_cooling_device *cooling_dev,
unsigned long *state)
{
struct int3406_thermal_data *d = cooling_dev->devdata;
int raw_level, level, i;
int *levels = d->br->levels;
int acpi_level;
int index;

raw_level = d->raw_bd->props.brightness;
level = int3406_thermal_to_acpi(raw_level, d);
acpi_level = RAW_TO_ACPI(d->raw_bd->props.brightness, d);

/*
* There is no 1:1 mapping between the firmware interface level with the
* raw interface level, we will have to find one that is close enough.
* There is no 1:1 mapping between the firmware interface level
* with the raw interface level, we will have to find one that is
* right above it.
*/
for (i = 2; i < d->br->count; i++) {
if (level < levels[i]) {
if (i == 2)
break;
if ((level - levels[i - 1]) < (levels[i] - level))
i--;
for (index = d->lower_limit; index < d->upper_limit; index++) {
if (acpi_level <= d->br->levels[index])
break;
}
}

*state = d->br->count - 1 - i;
*state = d->upper_limit - index;
return 0;
}

Expand All @@ -117,7 +102,7 @@ static int int3406_thermal_get_index(int *array, int nr, int value)
{
int i;

for (i = 0; i < nr; i++) {
for (i = 2; i < nr; i++) {
if (array[i] == value)
break;
}
Expand All @@ -128,27 +113,20 @@ static void int3406_thermal_get_limit(struct int3406_thermal_data *d)
{
acpi_status status;
unsigned long long lower_limit, upper_limit;
int index;

status = acpi_evaluate_integer(d->handle, "DDDL", NULL, &lower_limit);
if (ACPI_SUCCESS(status)) {
index = int3406_thermal_get_index(d->br->levels, d->br->count,
lower_limit);
if (index > 0) {
d->lower_limit = (int)lower_limit;
d->lower_limit_index = index;
}
}
if (ACPI_SUCCESS(status))
d->lower_limit = int3406_thermal_get_index(d->br->levels,
d->br->count, lower_limit);

status = acpi_evaluate_integer(d->handle, "DDPC", NULL, &upper_limit);
if (ACPI_SUCCESS(status)) {
index = int3406_thermal_get_index(d->br->levels, d->br->count,
upper_limit);
if (index > 0) {
d->upper_limit = (int)upper_limit;
d->upper_limit_index = index;
}
}
if (ACPI_SUCCESS(status))
d->upper_limit = int3406_thermal_get_index(d->br->levels,
d->br->count, upper_limit);

/* lower_limit and upper_limit should be always set */
d->lower_limit = d->lower_limit > 0 ? d->lower_limit : 2;
d->upper_limit = d->upper_limit > 0 ? d->upper_limit : d->br->count - 1;
}

static void int3406_notify(acpi_handle handle, u32 event, void *data)
Expand Down
Loading

0 comments on commit c971aa3

Please sign in to comment.