thermal\_core是thermal框架的核心,负责将thermal\_zone、thermal\_cooling和thermal\_governor连接起来
首先看下头文件thermal_core.h,
/* Initial state of a cooling device during binding */
#define THERMAL_NO_TARGET -1UL
/*
* This structure is used to describe the behavior of
* a certain cooling device on a certain trip point
* in a certain thermal zone
*/
// thermal_instance结构体定义
struct thermal_instance{
......
};
// 注册和卸载governor
int thermal_register_governor(struct thermal_governor *);
void thermal_unregister_governor(struct thermal_governor *);
// 下面通过宏判断使用哪个governor
#ifdef CONFIG_THERMAL_GOV_STEP_WISE
int thermal_gov_step_wise_register(void);
void thermal_gov_step_wise_unregister(void);
#else
static inline int thermal_gov_step_wise_register(void) { return 0; }
static inline void thermal_gov_step_wise_unregister(void) {}
#endif /* CONFIG_THERMAL_GOV_STEP_WISE */
...
...
/* device tree support */
#ifdef CONFIG_THERMAL_OF
int of_parse_thermal_zones(void);
void of_thermal_destroy_zones(void);
int of_thermal_get_ntrips(struct thermal_zone_device *);
bool of_thermal_is_trip_valid(struct thermal_zone_device *, int);
const struct thermal_trip *
of_thermal_get_trip_points(struct thermal_zone_device *);
#else
static inline int of_parse_thermal_zones(void) { return 0; }
static inline void of_thermal_destroy_zones(void)
static inline int of_thermal_get_ntrips(struct thermal_zone_device *tz)
{
return 0;
}
static inline bool of_thermal_is_trip_valid(struct thermal_zone_device *tz,
int trip)
{
return false;
}
static inline const struct thermal_trip *
of_thermal_get_trip_points(struct thermal_zone_device *tz)
{
return NULL;
}
#endif
#endif /* __THERMAL_CORE_H__ */
在thermal_core.c除了以上函数的具体实现,还包括一些其它函数,首先看一下thermal的初始化函数thermal\_init()函数:
static int __init thermal_init(void)
{
int result;
result = thermal_register_governors(); // 注册governor
if (result)
goto error;
result = class_register(&thermal_class); // 注册/sys/class/thermal
if (result)
goto unregister_governors;
result = genetlink_init(); // generic netlink初始化,干嘛的?
if (result)
goto unregister_class;
result = of_parse_thermal_zones(); // 解析dts文件中的“thermal-zone”节点,并注册thermal_zone_device
if (result)
goto exit_netlink;
result = register_pm_notifier(&thermal_pm_nb); // 注册notifier
if (result)
pr_warn("Thermal: Can not register suspend notifier, return %d\n",
result);
return 0;
exit_netlink:
genetlink_exit();
unregister_class:
class_unregister(&thermal_class);
unregister_governors:
thermal_unregister_governors();
error:
idr_destroy(&thermal_tz_idr);
idr_destroy(&thermal_cdev_idr);
mutex_destroy(&thermal_idr_lock);
mutex_destroy(&thermal_list_lock);
mutex_destroy(&thermal_governor_lock);
return result;
}
接下来,看一下of_parse_thermal_zones函数,我们从设备树文件中找个thermal-zones节点,如下所示
thermal-zones {
soc_thermal {
polling-delay = <1000>;
polling-delay-passive = <100>;
sustainable-power = <2150>;
thermal-sensors = <&aml_sensor0 3>;
trips {
switch_on: trip-point@0 {
temperature = <70000>;
hysteresis = <1000>;
type = "passive";
};
control: trip-point@1 {
temperature = <80000>;
hysteresis = <1000>;
type = "passive";
};
hot: trip-point@2 {
temperature = <85000>;
hysteresis = <5000>;
type = "hot";
};
critical: trip-point@3 {
temperature = <260000>;
hysteresis = <1000>;
type = "critical";
};
};
cooling-maps {
cpufreq_cooling_map {
trip = <&control>;
cooling-device = <&cpus 0 4>;
contribution = <1024>;
};
cpucore_cooling_map {
trip = <&control>;
cooling-device = <&cpu_cluster0 0 3>;
contribution = <1024>;
};
gpufreq_cooling_map {
trip = <&control>;
cooling-device = <&gpu 0 4>;
contribution = <1024>;
};
gpucore_cooling_map {
trip = <&control>;
cooling-device = <&gpucore 0 2>;
contribution = <1024>;
};
};
};
};
}; /* end of / */
再看一下of\_parse\_thermal\_zones函数的具体实现,
/**
* of_parse_thermal_zones - parse device tree thermal data
*
* Initialization function that can be called by machine initialization
* code to parse thermal data and populate the thermal framework
* with hardware thermal zones info. This function only parses thermal zones.
* Cooling devices and sensor devices nodes are supposed to be parsed
* by their respective drivers.
*
* Return: 0 on success, proper error code otherwise
*
*/
int __init of_parse_thermal_zones(void)
{
struct device_node *np, *child;
struct __thermal_zone *tz;
struct thermal_zone_device_ops *ops;
np = of_find_node_by_name(NULL, "thermal-zones");
if (!np) {
pr_debug("unable to find thermal zones\n");
return 0; /* Run successfully on systems without thermal DT */
}
for_each_available_child_of_node(np, child) {
struct thermal_zone_device *zone;
struct thermal_zone_params *tzp;
#ifdef CONFIG_AMLOGIC_TEMP_SENSOR
const char *str;
#endif
int i, mask = 0;
u32 prop;
tz = thermal_of_build_thermal_zone(child);
if (IS_ERR(tz)) {
pr_err("failed to build thermal zone %s: %ld\n",
child->name,
PTR_ERR(tz));
continue;
}
ops = kmemdup(&of_thermal_ops, sizeof(*ops), GFP_KERNEL);
if (!ops)
goto exit_free;
tzp = kzalloc(sizeof(*tzp), GFP_KERNEL);
if (!tzp) {
kfree(ops);
goto exit_free;
}
/* No hwmon because there might be hwmon drivers registering */
tzp->no_hwmon = true;
if (!of_property_read_u32(child, "sustainable-power", &prop))
tzp->sustainable_power = prop;
#ifdef CONFIG_AMLOGIC_TEMP_SENSOR
if (!of_property_read_string(child, "policy", &str))
strncpy(tzp->governor_name, str, THERMAL_NAME_LENGTH);
#endif
for (i = 0; i < tz->ntrips; i++)
mask |= 1 << i;
/* these two are left for temperature drivers to use */
tzp->slope = tz->slope;
tzp->offset = tz->offset;
// 注册thermal_zone_device
zone = thermal_zone_device_register(child->name, tz->ntrips,
mask, tz,
ops, tzp,
tz->passive_delay,
tz->polling_delay);
if (IS_ERR(zone)) {
pr_err("Failed to build %s zone %ld\n", child->name,
PTR_ERR(zone));
kfree(tzp);
kfree(ops);
of_thermal_free_zone(tz);
/* attempting to build remaining zones still */
}
}
of_node_put(np);
return 0;
exit_free:
of_node_put(child);
of_node_put(np);
of_thermal_free_zone(tz);
/* no memory available, so free what we have built */
of_thermal_destroy_zones();
return -ENOMEM;
}
在解析设备树函数中,将会调用thermal\_zone\_device设备注册函数,
评论 (0)