/* * It maps 'enum thermal_trip_type' found in include/linux/thermal.h * into the device tree binding of 'trip', property type.
*/ staticconstchar * const trip_types[] = {
[THERMAL_TRIP_ACTIVE] = "active",
[THERMAL_TRIP_PASSIVE] = "passive",
[THERMAL_TRIP_HOT] = "hot",
[THERMAL_TRIP_CRITICAL] = "critical",
};
/** * thermal_of_get_trip_type - Get phy mode for given device_node * @np: Pointer to the given device_node * @type: Pointer to resulting trip type * * The function gets trip type string from property 'type', * and store its index in trip_types table in @type, * * Return: 0 on success, or errno in error case.
*/ staticint thermal_of_get_trip_type(struct device_node *np, enum thermal_trip_type *type)
{ constchar *t; int err, i;
struct device_node *np __free(device_node) = of_find_node_by_name(NULL, "thermal-zones"); if (!np) {
pr_debug("No thermal zones description\n"); return ERR_PTR(-ENODEV);
}
/* * Search for each thermal zone, a defined sensor * corresponding to the one passed as parameter
*/
for_each_available_child_of_node_scoped(np, child) {
ret = of_parse_phandle_with_args(child, "thermal-sensors", "#thermal-sensor-cells",
i, &sensor_specs); if (ret < 0) {
pr_err("%pOFn: Failed to read thermal-sensors cells: %d\n", child, ret); return ERR_PTR(ret);
}
of_node_put(sensor_specs.np); if ((sensor == sensor_specs.np) && id == (sensor_specs.args_count ?
sensor_specs.args[0] : 0)) {
pr_debug("sensor %pOFn id=%d belongs to %pOFn\n", sensor, id, child); return no_free_ptr(child);
}
}
}
return ERR_PTR(-ENODEV);
}
staticint thermal_of_monitor_init(struct device_node *np, int *delay, int *pdelay)
{ int ret;
ret = of_property_read_u32(np, "polling-delay-passive", pdelay); if (ret == -EINVAL) {
*pdelay = 0;
} elseif (ret < 0) {
pr_err("%pOFn: Couldn't get polling-delay-passive: %d\n", np, ret); return ret;
}
ret = of_property_read_u32(np, "polling-delay", delay); if (ret == -EINVAL) {
*delay = 0;
} elseif (ret < 0) {
pr_err("%pOFn: Couldn't get polling-delay: %d\n", np, ret); return ret;
}
return 0;
}
staticvoid thermal_of_parameters_init(struct device_node *np, struct thermal_zone_params *tzp)
{ int coef[2]; int ncoef = ARRAY_SIZE(coef); int prop, ret;
tzp->no_hwmon = true;
if (!of_property_read_u32(np, "sustainable-power", &prop))
tzp->sustainable_power = prop;
/* * For now, the thermal framework supports only one sensor per * thermal zone. Thus, we are considering only the first two * values as slope and offset.
*/
ret = of_property_read_u32_array(np, "coefficients", coef, ncoef); if (ret) {
coef[0] = 1;
coef[1] = 0;
}
tr_np = of_parse_phandle(child, "trip", 0); if (tr_np != trip->priv) continue;
/* The trip has been found, look up the cdev. */
count = of_count_phandle_with_args(child, "cooling-device", "#cooling-cells"); if (count <= 0)
pr_err("Add a cooling_device property with at least one device\n");
for (i = 0; i < count; i++) { if (thermal_of_get_cooling_spec(child, i, cdev, c)) returntrue;
}
}
tz_np = thermal_of_zone_get_by_name(tz); if (IS_ERR(tz_np)) {
pr_err("Failed to get node tz by name\n"); returnfalse;
}
cm_np = of_get_child_by_name(tz_np, "cooling-maps"); if (!cm_np) goto out;
/* Look up the trip and the cdev in the cooling maps. */
result = thermal_of_cm_lookup(cm_np, trip, cdev, c);
of_node_put(cm_np);
out:
of_node_put(tz_np);
return result;
}
/** * thermal_of_zone_unregister - Cleanup the specific allocated ressources * * This function disables the thermal zone and frees the different * ressources allocated specific to the thermal OF. * * @tz: a pointer to the thermal zone structure
*/ staticvoid thermal_of_zone_unregister(struct thermal_zone_device *tz)
{
thermal_zone_device_disable(tz);
thermal_zone_device_unregister(tz);
}
/** * thermal_of_zone_register - Register a thermal zone with device node * sensor * * The thermal_of_zone_register() parses a device tree given a device * node sensor and identifier. It searches for the thermal zone * associated to the couple sensor/id and retrieves all the thermal * zone properties and registers new thermal zone with those * properties. * * @sensor: A device node pointer corresponding to the sensor in the device tree * @id: An integer as sensor identifier * @data: A private data to be stored in the thermal zone dedicated private area * @ops: A set of thermal sensor ops * * Return: a valid thermal zone structure pointer on success. * - EINVAL: if the device tree thermal description is malformed * - ENOMEM: if one structure can not be allocated * - Other negative errors are returned by the underlying called functions
*/ staticstruct thermal_zone_device *thermal_of_zone_register(struct device_node *sensor, int id, void *data, conststruct thermal_zone_device_ops *ops)
{ struct thermal_zone_device_ops of_ops = *ops; struct thermal_zone_device *tz; struct thermal_trip *trips; struct thermal_zone_params tzp = {}; struct device_node *np; constchar *action; int delay, pdelay; int ntrips; int ret;
np = of_thermal_zone_find(sensor, id); if (IS_ERR(np)) { if (PTR_ERR(np) != -ENODEV)
pr_err("Failed to find thermal zone for %pOFn id=%d\n", sensor, id); return ERR_CAST(np);
}
trips = thermal_of_trips_init(np, &ntrips); if (IS_ERR(trips)) {
pr_err("Failed to parse trip points for %pOFn id=%d\n", sensor, id);
ret = PTR_ERR(trips); goto out_of_node_put;
}
if (!trips)
pr_info("No trip points found for %pOFn id=%d\n", sensor, id);
ret = thermal_of_monitor_init(np, &delay, &pdelay); if (ret) {
pr_err("Failed to initialize monitoring delays from %pOFn\n", np); goto out_kfree_trips;
}
thermal_of_parameters_init(np, &tzp);
of_ops.should_bind = thermal_of_should_bind;
ret = of_property_read_string(np, "critical-action", &action); if (!ret && !of_ops.critical) { if (!strcasecmp(action, "reboot"))
of_ops.critical = thermal_zone_device_critical_reboot; elseif (!strcasecmp(action, "shutdown"))
of_ops.critical = thermal_zone_device_critical_shutdown;
}
tz = thermal_zone_device_register_with_trips(np->name, trips, ntrips,
data, &of_ops, &tzp,
pdelay, delay); if (IS_ERR(tz)) {
ret = PTR_ERR(tz);
pr_err("Failed to register thermal zone %pOFn: %d\n", np, ret); goto out_kfree_trips;
}
of_node_put(np);
kfree(trips);
ret = thermal_zone_device_enable(tz); if (ret) {
pr_err("Failed to enabled thermal zone '%s', id=%d: %d\n",
tz->type, tz->id, ret);
thermal_of_zone_unregister(tz); return ERR_PTR(ret);
}
/** * devm_thermal_of_zone_register - register a thermal tied with the sensor life cycle * * This function is the device version of the thermal_of_zone_register() function. * * @dev: a device structure pointer to sensor to be tied with the thermal zone OF life cycle * @sensor_id: the sensor identifier * @data: a pointer to a private data to be stored in the thermal zone 'devdata' field * @ops: a pointer to the ops structure associated with the sensor
*/ struct thermal_zone_device *devm_thermal_of_zone_register(struct device *dev, int sensor_id, void *data, conststruct thermal_zone_device_ops *ops)
{ struct thermal_zone_device **ptr, *tzd;
ptr = devres_alloc(devm_thermal_of_zone_release, sizeof(*ptr),
GFP_KERNEL); if (!ptr) return ERR_PTR(-ENOMEM);
/** * devm_thermal_of_zone_unregister - Resource managed version of * thermal_of_zone_unregister(). * @dev: Device for which which resource was allocated. * @tz: a pointer to struct thermal_zone where the sensor is registered. * * This function removes the sensor callbacks and private data from the * thermal zone device registered with devm_thermal_zone_of_sensor_register() * API. It will also silent the zone by remove the .get_temp() and .get_trend() * thermal zone device callbacks. * Normally this function will not need to be called and the resource * management code will ensure that the resource is freed.
*/ void devm_thermal_of_zone_unregister(struct device *dev, struct thermal_zone_device *tz)
{
WARN_ON(devres_release(dev, devm_thermal_of_zone_release,
devm_thermal_of_zone_match, tz));
}
EXPORT_SYMBOL_GPL(devm_thermal_of_zone_unregister);
Messung V0.5
¤ Dauer der Verarbeitung: 0.13 Sekunden
(vorverarbeitet)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.