Commit 4e5e4705 authored by Eduardo Valentin's avatar Eduardo Valentin

thermal: introduce device tree parser

This patch introduces a device tree bindings for
describing the hardware thermal behavior and limits.
Also a parser to read and interpret the data and feed
it in the thermal framework is presented.

This patch introduces a thermal data parser for device
tree. The parsed data is used to build thermal zones
and thermal binding parameters. The output data
can then be used to deploy thermal policies.

This patch adds also documentation regarding this
API and how to define tree nodes to use
this infrastructure.

Note that, in order to be able to have control
on the sensor registration on the DT thermal zone,
it was required to allow changing the thermal zone
.get_temp callback. For this reason, this patch
also removes the 'const' modifier from the .ops
field of thermal zone devices.

Cc: Zhang Rui <rui.zhang@intel.com>
Cc: linux-pm@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
Acked-by: default avatarMark Rutland <mark.rutland@arm.com>
Signed-off-by: default avatarEduardo Valentin <eduardo.valentin@ti.com>
parent 81bd4e1c
This diff is collapsed.
...@@ -29,6 +29,19 @@ config THERMAL_HWMON ...@@ -29,6 +29,19 @@ config THERMAL_HWMON
Say 'Y' here if you want all thermal sensors to Say 'Y' here if you want all thermal sensors to
have hwmon sysfs interface too. have hwmon sysfs interface too.
config THERMAL_OF
bool
prompt "APIs to parse thermal data out of device tree"
depends on OF
default y
help
This options provides helpers to add the support to
read and parse thermal data definitions out of the
device tree blob.
Say 'Y' here if you need to build thermal infrastructure
based on device tree.
choice choice
prompt "Default Thermal governor" prompt "Default Thermal governor"
default THERMAL_DEFAULT_GOV_STEP_WISE default THERMAL_DEFAULT_GOV_STEP_WISE
......
...@@ -7,6 +7,7 @@ thermal_sys-y += thermal_core.o ...@@ -7,6 +7,7 @@ thermal_sys-y += thermal_core.o
# interface to/from other layers providing sensors # interface to/from other layers providing sensors
thermal_sys-$(CONFIG_THERMAL_HWMON) += thermal_hwmon.o thermal_sys-$(CONFIG_THERMAL_HWMON) += thermal_hwmon.o
thermal_sys-$(CONFIG_THERMAL_OF) += of-thermal.o
# governors # governors
thermal_sys-$(CONFIG_THERMAL_GOV_FAIR_SHARE) += fair_share.o thermal_sys-$(CONFIG_THERMAL_GOV_FAIR_SHARE) += fair_share.o
......
This diff is collapsed.
...@@ -1373,7 +1373,7 @@ static void remove_trip_attrs(struct thermal_zone_device *tz) ...@@ -1373,7 +1373,7 @@ static void remove_trip_attrs(struct thermal_zone_device *tz)
*/ */
struct thermal_zone_device *thermal_zone_device_register(const char *type, struct thermal_zone_device *thermal_zone_device_register(const char *type,
int trips, int mask, void *devdata, int trips, int mask, void *devdata,
const struct thermal_zone_device_ops *ops, struct thermal_zone_device_ops *ops,
const struct thermal_zone_params *tzp, const struct thermal_zone_params *tzp,
int passive_delay, int polling_delay) int passive_delay, int polling_delay)
{ {
...@@ -1746,8 +1746,14 @@ static int __init thermal_init(void) ...@@ -1746,8 +1746,14 @@ static int __init thermal_init(void)
if (result) if (result)
goto unregister_class; goto unregister_class;
result = of_parse_thermal_zones();
if (result)
goto exit_netlink;
return 0; return 0;
exit_netlink:
genetlink_exit();
unregister_governors: unregister_governors:
thermal_unregister_governors(); thermal_unregister_governors();
unregister_class: unregister_class:
...@@ -1763,6 +1769,7 @@ static int __init thermal_init(void) ...@@ -1763,6 +1769,7 @@ static int __init thermal_init(void)
static void __exit thermal_exit(void) static void __exit thermal_exit(void)
{ {
of_thermal_destroy_zones();
genetlink_exit(); genetlink_exit();
class_unregister(&thermal_class); class_unregister(&thermal_class);
thermal_unregister_governors(); thermal_unregister_governors();
......
...@@ -77,4 +77,13 @@ static inline int thermal_gov_user_space_register(void) { return 0; } ...@@ -77,4 +77,13 @@ static inline int thermal_gov_user_space_register(void) { return 0; }
static inline void thermal_gov_user_space_unregister(void) {} static inline void thermal_gov_user_space_unregister(void) {}
#endif /* CONFIG_THERMAL_GOV_USER_SPACE */ #endif /* CONFIG_THERMAL_GOV_USER_SPACE */
/* device tree support */
#ifdef CONFIG_THERMAL_OF
int of_parse_thermal_zones(void);
void of_thermal_destroy_zones(void);
#else
static inline int of_parse_thermal_zones(void) { return 0; }
static inline void of_thermal_destroy_zones(void) { }
#endif
#endif /* __THERMAL_CORE_H__ */ #endif /* __THERMAL_CORE_H__ */
/*
* This header provides constants for most thermal bindings.
*
* Copyright (C) 2013 Texas Instruments
* Eduardo Valentin <eduardo.valentin@ti.com>
*
* GPLv2 only
*/
#ifndef _DT_BINDINGS_THERMAL_THERMAL_H
#define _DT_BINDINGS_THERMAL_THERMAL_H
/* On cooling devices upper and lower limits */
#define THERMAL_NO_LIMIT (-1UL)
#endif
...@@ -143,6 +143,7 @@ struct thermal_cooling_device { ...@@ -143,6 +143,7 @@ struct thermal_cooling_device {
int id; int id;
char type[THERMAL_NAME_LENGTH]; char type[THERMAL_NAME_LENGTH];
struct device device; struct device device;
struct device_node *np;
void *devdata; void *devdata;
const struct thermal_cooling_device_ops *ops; const struct thermal_cooling_device_ops *ops;
bool updated; /* true if the cooling device does not need update */ bool updated; /* true if the cooling device does not need update */
...@@ -172,7 +173,7 @@ struct thermal_zone_device { ...@@ -172,7 +173,7 @@ struct thermal_zone_device {
int emul_temperature; int emul_temperature;
int passive; int passive;
unsigned int forced_passive; unsigned int forced_passive;
const struct thermal_zone_device_ops *ops; struct thermal_zone_device_ops *ops;
const struct thermal_zone_params *tzp; const struct thermal_zone_params *tzp;
struct thermal_governor *governor; struct thermal_governor *governor;
struct list_head thermal_instances; struct list_head thermal_instances;
...@@ -242,8 +243,31 @@ struct thermal_genl_event { ...@@ -242,8 +243,31 @@ struct thermal_genl_event {
}; };
/* Function declarations */ /* Function declarations */
#ifdef CONFIG_THERMAL_OF
struct thermal_zone_device *
thermal_zone_of_sensor_register(struct device *dev, int id,
void *data, int (*get_temp)(void *, long *),
int (*get_trend)(void *, long *));
void thermal_zone_of_sensor_unregister(struct device *dev,
struct thermal_zone_device *tz);
#else
static inline struct thermal_zone_device *
thermal_zone_of_sensor_register(struct device *dev, int id,
void *data, int (*get_temp)(void *, long *),
int (*get_trend)(void *, long *))
{
return NULL;
}
static inline
void thermal_zone_of_sensor_unregister(struct device *dev,
struct thermal_zone_device *tz)
{
}
#endif
struct thermal_zone_device *thermal_zone_device_register(const char *, int, int, struct thermal_zone_device *thermal_zone_device_register(const char *, int, int,
void *, const struct thermal_zone_device_ops *, void *, struct thermal_zone_device_ops *,
const struct thermal_zone_params *, int, int); const struct thermal_zone_params *, int, int);
void thermal_zone_device_unregister(struct thermal_zone_device *); void thermal_zone_device_unregister(struct thermal_zone_device *);
......
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