--- zzzz-none-000/linux-4.4.271/drivers/thermal/of-thermal.c 2021-06-03 06:22:09.000000000 +0000 +++ hawkeye-5590-750/linux-4.4.271/drivers/thermal/of-thermal.c 2023-04-19 10:22:29.000000000 +0000 @@ -31,6 +31,7 @@ #include #include #include +#include #include "thermal_core.h" @@ -101,6 +102,28 @@ return data->ops->get_temp(data->sensor_data, temp); } +static int of_thermal_set_trips(struct thermal_zone_device *tz, + int low, int high) +{ + struct __thermal_zone *data = tz->devdata; + + if (!data->ops || !data->ops->set_trips) + return -EINVAL; + + return data->ops->set_trips(data->sensor_data, low, high); +} + +static int of_thermal_panic_notify(struct thermal_zone_device *tz) +{ + struct __thermal_zone *data = tz->devdata; + + if ((data->ops->panic_notify) && + (data->mode != THERMAL_DEVICE_DISABLED)) + data->ops->panic_notify(data->sensor_data); + + return 0; +} + /** * of_thermal_get_ntrips - function to export number of available trip * points. @@ -181,9 +204,6 @@ { struct __thermal_zone *data = tz->devdata; - if (!data->ops || !data->ops->set_emul_temp) - return -EINVAL; - return data->ops->set_emul_temp(data->sensor_data, temp); } @@ -191,25 +211,11 @@ enum thermal_trend *trend) { struct __thermal_zone *data = tz->devdata; - long dev_trend; - int r; if (!data->ops->get_trend) return -EINVAL; - r = data->ops->get_trend(data->sensor_data, &dev_trend); - if (r) - return r; - - /* TODO: These intervals might have some thresholds, but in core code */ - if (dev_trend > 0) - *trend = THERMAL_TREND_RAISING; - else if (dev_trend < 0) - *trend = THERMAL_TREND_DROPPING; - else - *trend = THERMAL_TREND_STABLE; - - return 0; + return data->ops->get_trend(data->sensor_data, trip, trend); } static int of_thermal_bind(struct thermal_zone_device *thermal, @@ -313,6 +319,31 @@ return 0; } +static int of_thermal_activate_trip_type(struct thermal_zone_device *tz, + int trip, enum thermal_trip_activation_mode mode) +{ + struct __thermal_zone *data = tz->devdata; + + if (trip >= data->ntrips || trip < 0) + return -EDOM; + + /* + * The configurable_hi and configurable_lo trip points can be + * activated and deactivated. + */ + + if (data->ops->set_trip_activate) { + int ret; + + ret = data->ops->set_trip_activate(data->sensor_data, + trip, mode); + if (ret) + return ret; + } + + return 0; +} + static int of_thermal_get_trip_temp(struct thermal_zone_device *tz, int trip, int *temp) { @@ -334,6 +365,14 @@ if (trip >= data->ntrips || trip < 0) return -EDOM; + if (data->ops->set_trip_temp) { + int ret; + + ret = data->ops->set_trip_temp(data->sensor_data, trip, temp); + if (ret) + return ret; + } + /* thermal framework should take care of data->mask & (1 << trip) */ data->trips[trip].temperature = temp; @@ -421,13 +460,41 @@ tz->sensor_data = data; tzd->ops->get_temp = of_thermal_get_temp; + tzd->ops->panic_notify = of_thermal_panic_notify; tzd->ops->get_trend = of_thermal_get_trend; - tzd->ops->set_emul_temp = of_thermal_set_emul_temp; + + /* + * The thermal zone core will calculate the window if they have set the + * optional set_trips pointer. + */ + if (ops->set_trips) + tzd->ops->set_trips = of_thermal_set_trips; + + if (ops->set_emul_temp) + tzd->ops->set_emul_temp = of_thermal_set_emul_temp; + + if (ops->set_trip_activate) + tzd->ops->set_trip_activate = of_thermal_activate_trip_type; + mutex_unlock(&tzd->lock); return tzd; } +#define CONVERT_TO_DEZI_CELSIUS(x) ((x)*10) + +int read_temp_callback(void *avm_power_handle, void *context, int *value) +{ + struct thermal_zone_device *tzd = context; + int ret; + + ret = thermal_zone_get_temp(tzd, value); + if (!ret) + *value = CONVERT_TO_DEZI_CELSIUS(*value); + + return ret; +} + /** * thermal_zone_of_sensor_register - registers a sensor to a DT thermal zone * @dev: a valid struct device pointer of a sensor device. Must contain @@ -478,14 +545,10 @@ sensor_np = of_node_get(dev->of_node); - for_each_child_of_node(np, child) { + for_each_available_child_of_node(np, child) { struct of_phandle_args sensor_specs; int ret, id; - /* Check whether child is enabled or not */ - if (!of_device_is_available(child)) - continue; - /* For now, thermal framework supports only 1 sensor per zone */ ret = of_parse_phandle_with_args(child, "thermal-sensors", "#thermal-sensor-cells", @@ -518,6 +581,9 @@ of_node_put(sensor_np); of_node_put(np); + if (!IS_ERR(tzd)) + tzd->avm_power_handle = TemperaturSensorRegister(tzd->type, + read_temp_callback, tzd); return tzd; } EXPORT_SYMBOL_GPL(thermal_zone_of_sensor_register); @@ -545,6 +611,9 @@ if (!dev || !tzd || !tzd->devdata) return; + if (tzd->avm_power_handle) + TemperaturSensorDeregister(tzd->avm_power_handle); + tz = tzd->devdata; /* no __thermal_zone, nothing to be done */ @@ -562,6 +631,87 @@ } EXPORT_SYMBOL_GPL(thermal_zone_of_sensor_unregister); +static void devm_thermal_zone_of_sensor_release(struct device *dev, void *res) +{ + thermal_zone_of_sensor_unregister(dev, + *(struct thermal_zone_device **)res); +} + +static int devm_thermal_zone_of_sensor_match(struct device *dev, void *res, + void *data) +{ + struct thermal_zone_device **r = res; + + if (WARN_ON(!r || !*r)) + return 0; + + return *r == data; +} + +/** + * devm_thermal_zone_of_sensor_register - Resource managed version of + * thermal_zone_of_sensor_register() + * @dev: a valid struct device pointer of a sensor device. Must contain + * a valid .of_node, for the sensor node. + * @sensor_id: a sensor identifier, in case the sensor IP has more + * than one sensors + * @data: a private pointer (owned by the caller) that will be passed + * back, when a temperature reading is needed. + * @ops: struct thermal_zone_of_device_ops *. Must contain at least .get_temp. + * + * Refer thermal_zone_of_sensor_register() for more details. + * + * Return: On success returns a valid struct thermal_zone_device, + * otherwise, it returns a corresponding ERR_PTR(). Caller must + * check the return value with help of IS_ERR() helper. + * Registered thermal_zone_device device will automatically be + * released when device is unbounded. + */ +struct thermal_zone_device *devm_thermal_zone_of_sensor_register( + struct device *dev, int sensor_id, + void *data, const struct thermal_zone_of_device_ops *ops) +{ + struct thermal_zone_device **ptr, *tzd; + + ptr = devres_alloc(devm_thermal_zone_of_sensor_release, sizeof(*ptr), + GFP_KERNEL); + if (!ptr) + return ERR_PTR(-ENOMEM); + + tzd = thermal_zone_of_sensor_register(dev, sensor_id, data, ops); + if (IS_ERR(tzd)) { + devres_free(ptr); + return tzd; + } + + *ptr = tzd; + devres_add(dev, ptr); + + return tzd; +} +EXPORT_SYMBOL_GPL(devm_thermal_zone_of_sensor_register); + +/** + * devm_thermal_zone_of_sensor_unregister - Resource managed version of + * thermal_zone_of_sensor_unregister(). + * @dev: Device for which which resource was allocated. + * @tzd: a pointer to struct thermal_zone_device 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_zone_of_sensor_unregister(struct device *dev, + struct thermal_zone_device *tzd) +{ + WARN_ON(devres_release(dev, devm_thermal_zone_of_sensor_release, + devm_thermal_zone_of_sensor_match, tzd)); +} +EXPORT_SYMBOL_GPL(devm_thermal_zone_of_sensor_unregister); + /*** functions parsing device tree nodes ***/ /** @@ -640,7 +790,11 @@ [THERMAL_TRIP_ACTIVE] = "active", [THERMAL_TRIP_PASSIVE] = "passive", [THERMAL_TRIP_HOT] = "hot", - [THERMAL_TRIP_CRITICAL] = "critical", + [THERMAL_TRIP_CRITICAL] = "critical_high", + [THERMAL_TRIP_CONFIGURABLE_HI] = "configurable_hi", + [THERMAL_TRIP_CONFIGURABLE_LOW] = "configurable_lo", + [THERMAL_TRIP_CRITICAL_LOW] = "critical_low", + [THERMAL_TRIP_AVM_HOT] = "avm_hot", }; /** @@ -729,8 +883,8 @@ * otherwise, it returns a corresponding ERR_PTR(). Caller must * check the return value with help of IS_ERR() helper. */ -static struct __thermal_zone * -thermal_of_build_thermal_zone(struct device_node *np) +static struct __thermal_zone +__init *thermal_of_build_thermal_zone(struct device_node *np) { struct device_node *child = NULL, *gchild; struct __thermal_zone *tz; @@ -832,7 +986,7 @@ return tz; free_tbps: - for (i = 0; i < tz->num_tbps; i++) + for (i = i - 1; i >= 0; i--) of_node_put(tz->tbps[i].cooling_device); kfree(tz->tbps); free_trips: @@ -884,16 +1038,12 @@ return 0; /* Run successfully on systems without thermal DT */ } - for_each_child_of_node(np, child) { + for_each_available_child_of_node(np, child) { struct thermal_zone_device *zone; struct thermal_zone_params *tzp; int i, mask = 0; u32 prop; - /* Check whether child is enabled or not */ - if (!of_device_is_available(child)) - continue; - tz = thermal_of_build_thermal_zone(child); if (IS_ERR(tz)) { pr_err("failed to build thermal zone %s: %ld\n", @@ -971,13 +1121,9 @@ return; } - for_each_child_of_node(np, child) { + for_each_available_child_of_node(np, child) { struct thermal_zone_device *zone; - /* Check whether child is enabled or not */ - if (!of_device_is_available(child)) - continue; - zone = thermal_zone_get_zone_by_name(child->name); if (IS_ERR(zone)) continue;