Commit 79b20270 authored by Rafael J. Wysocki's avatar Rafael J. Wysocki
Browse files

Merge back thermal control material for 6.3.

parents acd7e9ee 02be6059
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -13,6 +13,7 @@ properties:
    enum:
      - qcom,spmi-adc-tm5
      - qcom,spmi-adc-tm5-gen2
      - qcom,adc-tm7 # Incomplete / subject to change

  reg:
    maxItems: 1
+143 −10
Original line number Diff line number Diff line
@@ -37,6 +37,7 @@ properties:
      - description: v1 of TSENS
        items:
          - enum:
              - qcom,msm8956-tsens
              - qcom,msm8976-tsens
              - qcom,qcs404-tsens
          - const: qcom,tsens-v1
@@ -80,18 +81,120 @@ properties:
    maxItems: 2

  nvmem-cells:
    minItems: 1
    oneOf:
      - minItems: 1
        maxItems: 2
        description:
          Reference to an nvmem node for the calibration data
      - minItems: 5
        maxItems: 35
        description: |
          Reference to nvmem cells for the calibration mode, two calibration
          bases and two cells per each sensor
        # special case for msm8974 / apq8084
      - maxItems: 51
        description: |
          Reference to nvmem cells for the calibration mode, two calibration
          bases and two cells per each sensor, main and backup copies, plus use_backup cell

  nvmem-cell-names:
    minItems: 1
    oneOf:
      - minItems: 1
        items:
          - const: calib
          - enum:
              - calib_backup
              - calib_sel
      - minItems: 5
        items:
          - const: mode
          - const: base1
          - const: base2
          - pattern: '^s[0-9]+_p1$'
          - pattern: '^s[0-9]+_p2$'
          - pattern: '^s[0-9]+_p1$'
          - pattern: '^s[0-9]+_p2$'
          - pattern: '^s[0-9]+_p1$'
          - pattern: '^s[0-9]+_p2$'
          - pattern: '^s[0-9]+_p1$'
          - pattern: '^s[0-9]+_p2$'
          - pattern: '^s[0-9]+_p1$'
          - pattern: '^s[0-9]+_p2$'
          - pattern: '^s[0-9]+_p1$'
          - pattern: '^s[0-9]+_p2$'
          - pattern: '^s[0-9]+_p1$'
          - pattern: '^s[0-9]+_p2$'
          - pattern: '^s[0-9]+_p1$'
          - pattern: '^s[0-9]+_p2$'
          - pattern: '^s[0-9]+_p1$'
          - pattern: '^s[0-9]+_p2$'
          - pattern: '^s[0-9]+_p1$'
          - pattern: '^s[0-9]+_p2$'
          - pattern: '^s[0-9]+_p1$'
          - pattern: '^s[0-9]+_p2$'
          - pattern: '^s[0-9]+_p1$'
          - pattern: '^s[0-9]+_p2$'
          - pattern: '^s[0-9]+_p1$'
          - pattern: '^s[0-9]+_p2$'
          - pattern: '^s[0-9]+_p1$'
          - pattern: '^s[0-9]+_p2$'
          - pattern: '^s[0-9]+_p1$'
          - pattern: '^s[0-9]+_p2$'
          - pattern: '^s[0-9]+_p1$'
          - pattern: '^s[0-9]+_p2$'
        # special case for msm8974 / apq8084
      - items:
          - const: mode
          - const: base1
          - const: base2
          - const: use_backup
          - const: mode_backup
          - const: base1_backup
          - const: base2_backup
          - const: s0_p1
          - const: s0_p2
          - const: s1_p1
          - const: s1_p2
          - const: s2_p1
          - const: s2_p2
          - const: s3_p1
          - const: s3_p2
          - const: s4_p1
          - const: s4_p2
          - const: s5_p1
          - const: s5_p2
          - const: s6_p1
          - const: s6_p2
          - const: s7_p1
          - const: s7_p2
          - const: s8_p1
          - const: s8_p2
          - const: s9_p1
          - const: s9_p2
          - const: s10_p1
          - const: s10_p2
          - const: s0_p1_backup
          - const: s0_p2_backup
          - const: s1_p1_backup
          - const: s1_p2_backup
          - const: s2_p1_backup
          - const: s2_p2_backup
          - const: s3_p1_backup
          - const: s3_p2_backup
          - const: s4_p1_backup
          - const: s4_p2_backup
          - const: s5_p1_backup
          - const: s5_p2_backup
          - const: s6_p1_backup
          - const: s6_p2_backup
          - const: s7_p1_backup
          - const: s7_p2_backup
          - const: s8_p1_backup
          - const: s8_p2_backup
          - const: s9_p1_backup
          - const: s9_p2_backup
          - const: s10_p1_backup
          - const: s10_p2_backup

  "#qcom,sensors":
    description:
@@ -220,6 +323,36 @@ examples:
          };
    };

  - |
    #include <dt-bindings/interrupt-controller/arm-gic.h>
    // Example 1 (new calbiration data: for pre v1 IP):
    thermal-sensor@900000 {
        compatible = "qcom,msm8916-tsens", "qcom,tsens-v0_1";
        reg = <0x4a9000 0x1000>, /* TM */
              <0x4a8000 0x1000>; /* SROT */

        nvmem-cells = <&tsens_mode>,
                      <&tsens_base1>, <&tsens_base2>,
                      <&tsens_s0_p1>, <&tsens_s0_p2>,
                      <&tsens_s1_p1>, <&tsens_s1_p2>,
                      <&tsens_s2_p1>, <&tsens_s2_p2>,
                      <&tsens_s4_p1>, <&tsens_s4_p2>,
                      <&tsens_s5_p1>, <&tsens_s5_p2>;
        nvmem-cell-names = "mode",
                           "base1", "base2",
                           "s0_p1", "s0_p2",
                           "s1_p1", "s1_p2",
                           "s2_p1", "s2_p2",
                           "s4_p1", "s4_p2",
                           "s5_p1", "s5_p2";

        interrupts = <GIC_SPI 184 IRQ_TYPE_LEVEL_HIGH>;
        interrupt-names = "uplow";

        #qcom,sensors = <5>;
        #thermal-sensor-cells = <1>;
    };

  - |
    #include <dt-bindings/interrupt-controller/arm-gic.h>
    // Example 1 (legacy: for pre v1 IP):
+0 −2
Original line number Diff line number Diff line
@@ -1079,8 +1079,6 @@ struct mbox_list {
#if IS_ENABLED(CONFIG_THERMAL)
struct ch_thermal {
	struct thermal_zone_device *tzdev;
	int trip_temp;
	int trip_type;
};
#endif

+7 −32
Original line number Diff line number Diff line
@@ -29,36 +29,12 @@ static int cxgb4_thermal_get_temp(struct thermal_zone_device *tzdev,
	return 0;
}

static int cxgb4_thermal_get_trip_type(struct thermal_zone_device *tzdev,
				       int trip, enum thermal_trip_type *type)
{
	struct adapter *adap = tzdev->devdata;

	if (!adap->ch_thermal.trip_temp)
		return -EINVAL;

	*type = adap->ch_thermal.trip_type;
	return 0;
}

static int cxgb4_thermal_get_trip_temp(struct thermal_zone_device *tzdev,
				       int trip, int *temp)
{
	struct adapter *adap = tzdev->devdata;

	if (!adap->ch_thermal.trip_temp)
		return -EINVAL;

	*temp = adap->ch_thermal.trip_temp;
	return 0;
}

static struct thermal_zone_device_ops cxgb4_thermal_ops = {
	.get_temp = cxgb4_thermal_get_temp,
	.get_trip_type = cxgb4_thermal_get_trip_type,
	.get_trip_temp = cxgb4_thermal_get_trip_temp,
};

static struct thermal_trip trip = { .type = THERMAL_TRIP_CRITICAL } ;

int cxgb4_thermal_init(struct adapter *adap)
{
	struct ch_thermal *ch_thermal = &adap->ch_thermal;
@@ -79,12 +55,11 @@ int cxgb4_thermal_init(struct adapter *adap)
	if (ret < 0) {
		num_trip = 0; /* could not get trip temperature */
	} else {
		ch_thermal->trip_temp = val * 1000;
		ch_thermal->trip_type = THERMAL_TRIP_CRITICAL;
		trip.temperature = val * 1000;
	}

	snprintf(ch_tz_name, sizeof(ch_tz_name), "cxgb4_%s", adap->name);
	ch_thermal->tzdev = thermal_zone_device_register(ch_tz_name, num_trip,
	ch_thermal->tzdev = thermal_zone_device_register_with_trips(ch_tz_name, &trip, num_trip,
								    0, adap,
								    &cxgb4_thermal_ops,
								    NULL, 0, 0);
+48 −161
Original line number Diff line number Diff line
@@ -36,33 +36,39 @@ enum mlxsw_thermal_trips {
	MLXSW_THERMAL_TEMP_TRIP_HOT,
};

struct mlxsw_thermal_trip {
	int	type;
	int	temp;
	int	hyst;
struct mlxsw_cooling_states {
	int	min_state;
	int	max_state;
};

static const struct mlxsw_thermal_trip default_thermal_trips[] = {
static const struct thermal_trip default_thermal_trips[] = {
	{	/* In range - 0-40% PWM */
		.type		= THERMAL_TRIP_ACTIVE,
		.temp		= MLXSW_THERMAL_ASIC_TEMP_NORM,
		.hyst		= MLXSW_THERMAL_HYSTERESIS_TEMP,
		.min_state	= 0,
		.max_state	= (4 * MLXSW_THERMAL_MAX_STATE) / 10,
		.temperature	= MLXSW_THERMAL_ASIC_TEMP_NORM,
		.hysteresis	= MLXSW_THERMAL_HYSTERESIS_TEMP,
	},
	{
		/* In range - 40-100% PWM */
		.type		= THERMAL_TRIP_ACTIVE,
		.temp		= MLXSW_THERMAL_ASIC_TEMP_HIGH,
		.hyst		= MLXSW_THERMAL_HYSTERESIS_TEMP,
		.min_state	= (4 * MLXSW_THERMAL_MAX_STATE) / 10,
		.max_state	= MLXSW_THERMAL_MAX_STATE,
		.temperature	= MLXSW_THERMAL_ASIC_TEMP_HIGH,
		.hysteresis	= MLXSW_THERMAL_HYSTERESIS_TEMP,
	},
	{	/* Warning */
		.type		= THERMAL_TRIP_HOT,
		.temp		= MLXSW_THERMAL_ASIC_TEMP_HOT,
		.temperature	= MLXSW_THERMAL_ASIC_TEMP_HOT,
	},
};

static const struct mlxsw_cooling_states default_cooling_states[] = {
	{
		.min_state	= 0,
		.max_state	= (4 * MLXSW_THERMAL_MAX_STATE) / 10,
	},
	{
		.min_state	= (4 * MLXSW_THERMAL_MAX_STATE) / 10,
		.max_state	= MLXSW_THERMAL_MAX_STATE,
	},
	{
		.min_state	= MLXSW_THERMAL_MAX_STATE,
		.max_state	= MLXSW_THERMAL_MAX_STATE,
	},
@@ -78,7 +84,8 @@ struct mlxsw_thermal;
struct mlxsw_thermal_module {
	struct mlxsw_thermal *parent;
	struct thermal_zone_device *tzdev;
	struct mlxsw_thermal_trip trips[MLXSW_THERMAL_NUM_TRIPS];
	struct thermal_trip trips[MLXSW_THERMAL_NUM_TRIPS];
	struct mlxsw_cooling_states cooling_states[MLXSW_THERMAL_NUM_TRIPS];
	int module; /* Module or gearbox number */
	u8 slot_index;
};
@@ -99,7 +106,8 @@ struct mlxsw_thermal {
	int polling_delay;
	struct thermal_cooling_device *cdevs[MLXSW_MFCR_PWMS_MAX];
	u8 cooling_levels[MLXSW_THERMAL_MAX_STATE + 1];
	struct mlxsw_thermal_trip trips[MLXSW_THERMAL_NUM_TRIPS];
	struct thermal_trip trips[MLXSW_THERMAL_NUM_TRIPS];
	struct mlxsw_cooling_states cooling_states[MLXSW_THERMAL_NUM_TRIPS];
	struct mlxsw_thermal_area line_cards[];
};

@@ -136,9 +144,9 @@ static int mlxsw_get_cooling_device_idx(struct mlxsw_thermal *thermal,
static void
mlxsw_thermal_module_trips_reset(struct mlxsw_thermal_module *tz)
{
	tz->trips[MLXSW_THERMAL_TEMP_TRIP_NORM].temp = 0;
	tz->trips[MLXSW_THERMAL_TEMP_TRIP_HIGH].temp = 0;
	tz->trips[MLXSW_THERMAL_TEMP_TRIP_HOT].temp = 0;
	tz->trips[MLXSW_THERMAL_TEMP_TRIP_NORM].temperature = 0;
	tz->trips[MLXSW_THERMAL_TEMP_TRIP_HIGH].temperature = 0;
	tz->trips[MLXSW_THERMAL_TEMP_TRIP_HOT].temperature = 0;
}

static int
@@ -180,12 +188,12 @@ mlxsw_thermal_module_trips_update(struct device *dev, struct mlxsw_core *core,
	 * by subtracting double hysteresis value.
	 */
	if (crit_temp >= MLXSW_THERMAL_MODULE_TEMP_SHIFT)
		tz->trips[MLXSW_THERMAL_TEMP_TRIP_NORM].temp = crit_temp -
		tz->trips[MLXSW_THERMAL_TEMP_TRIP_NORM].temperature = crit_temp -
					MLXSW_THERMAL_MODULE_TEMP_SHIFT;
	else
		tz->trips[MLXSW_THERMAL_TEMP_TRIP_NORM].temp = crit_temp;
	tz->trips[MLXSW_THERMAL_TEMP_TRIP_HIGH].temp = crit_temp;
	tz->trips[MLXSW_THERMAL_TEMP_TRIP_HOT].temp = emerg_temp;
		tz->trips[MLXSW_THERMAL_TEMP_TRIP_NORM].temperature = crit_temp;
	tz->trips[MLXSW_THERMAL_TEMP_TRIP_HIGH].temperature = crit_temp;
	tz->trips[MLXSW_THERMAL_TEMP_TRIP_HOT].temperature = emerg_temp;

	return 0;
}
@@ -202,11 +210,11 @@ static int mlxsw_thermal_bind(struct thermal_zone_device *tzdev,
		return 0;

	for (i = 0; i < MLXSW_THERMAL_NUM_TRIPS; i++) {
		const struct mlxsw_thermal_trip *trip = &thermal->trips[i];
		const struct mlxsw_cooling_states *state = &thermal->cooling_states[i];

		err = thermal_zone_bind_cooling_device(tzdev, i, cdev,
						       trip->max_state,
						       trip->min_state,
						       state->max_state,
						       state->min_state,
						       THERMAL_WEIGHT_DEFAULT);
		if (err < 0) {
			dev_err(dev, "Failed to bind cooling device to trip %d\n", i);
@@ -260,61 +268,6 @@ static int mlxsw_thermal_get_temp(struct thermal_zone_device *tzdev,
	return 0;
}

static int mlxsw_thermal_get_trip_type(struct thermal_zone_device *tzdev,
				       int trip,
				       enum thermal_trip_type *p_type)
{
	struct mlxsw_thermal *thermal = tzdev->devdata;

	if (trip < 0 || trip >= MLXSW_THERMAL_NUM_TRIPS)
		return -EINVAL;

	*p_type = thermal->trips[trip].type;
	return 0;
}

static int mlxsw_thermal_get_trip_temp(struct thermal_zone_device *tzdev,
				       int trip, int *p_temp)
{
	struct mlxsw_thermal *thermal = tzdev->devdata;

	if (trip < 0 || trip >= MLXSW_THERMAL_NUM_TRIPS)
		return -EINVAL;

	*p_temp = thermal->trips[trip].temp;
	return 0;
}

static int mlxsw_thermal_set_trip_temp(struct thermal_zone_device *tzdev,
				       int trip, int temp)
{
	struct mlxsw_thermal *thermal = tzdev->devdata;

	if (trip < 0 || trip >= MLXSW_THERMAL_NUM_TRIPS)
		return -EINVAL;

	thermal->trips[trip].temp = temp;
	return 0;
}

static int mlxsw_thermal_get_trip_hyst(struct thermal_zone_device *tzdev,
				       int trip, int *p_hyst)
{
	struct mlxsw_thermal *thermal = tzdev->devdata;

	*p_hyst = thermal->trips[trip].hyst;
	return 0;
}

static int mlxsw_thermal_set_trip_hyst(struct thermal_zone_device *tzdev,
				       int trip, int hyst)
{
	struct mlxsw_thermal *thermal = tzdev->devdata;

	thermal->trips[trip].hyst = hyst;
	return 0;
}

static struct thermal_zone_params mlxsw_thermal_params = {
	.no_hwmon = true,
};
@@ -323,11 +276,6 @@ static struct thermal_zone_device_ops mlxsw_thermal_ops = {
	.bind = mlxsw_thermal_bind,
	.unbind = mlxsw_thermal_unbind,
	.get_temp = mlxsw_thermal_get_temp,
	.get_trip_type	= mlxsw_thermal_get_trip_type,
	.get_trip_temp	= mlxsw_thermal_get_trip_temp,
	.set_trip_temp	= mlxsw_thermal_set_trip_temp,
	.get_trip_hyst	= mlxsw_thermal_get_trip_hyst,
	.set_trip_hyst	= mlxsw_thermal_set_trip_hyst,
};

static int mlxsw_thermal_module_bind(struct thermal_zone_device *tzdev,
@@ -342,11 +290,11 @@ static int mlxsw_thermal_module_bind(struct thermal_zone_device *tzdev,
		return 0;

	for (i = 0; i < MLXSW_THERMAL_NUM_TRIPS; i++) {
		const struct mlxsw_thermal_trip *trip = &tz->trips[i];
		const struct mlxsw_cooling_states *state = &tz->cooling_states[i];

		err = thermal_zone_bind_cooling_device(tzdev, i, cdev,
						       trip->max_state,
						       trip->min_state,
						       state->max_state,
						       state->min_state,
						       THERMAL_WEIGHT_DEFAULT);
		if (err < 0)
			goto err_thermal_zone_bind_cooling_device;
@@ -434,74 +382,10 @@ static int mlxsw_thermal_module_temp_get(struct thermal_zone_device *tzdev,
	return 0;
}

static int
mlxsw_thermal_module_trip_type_get(struct thermal_zone_device *tzdev, int trip,
				   enum thermal_trip_type *p_type)
{
	struct mlxsw_thermal_module *tz = tzdev->devdata;

	if (trip < 0 || trip >= MLXSW_THERMAL_NUM_TRIPS)
		return -EINVAL;

	*p_type = tz->trips[trip].type;
	return 0;
}

static int
mlxsw_thermal_module_trip_temp_get(struct thermal_zone_device *tzdev,
				   int trip, int *p_temp)
{
	struct mlxsw_thermal_module *tz = tzdev->devdata;

	if (trip < 0 || trip >= MLXSW_THERMAL_NUM_TRIPS)
		return -EINVAL;

	*p_temp = tz->trips[trip].temp;
	return 0;
}

static int
mlxsw_thermal_module_trip_temp_set(struct thermal_zone_device *tzdev,
				   int trip, int temp)
{
	struct mlxsw_thermal_module *tz = tzdev->devdata;

	if (trip < 0 || trip >= MLXSW_THERMAL_NUM_TRIPS)
		return -EINVAL;

	tz->trips[trip].temp = temp;
	return 0;
}

static int
mlxsw_thermal_module_trip_hyst_get(struct thermal_zone_device *tzdev, int trip,
				   int *p_hyst)
{
	struct mlxsw_thermal_module *tz = tzdev->devdata;

	*p_hyst = tz->trips[trip].hyst;
	return 0;
}

static int
mlxsw_thermal_module_trip_hyst_set(struct thermal_zone_device *tzdev, int trip,
				   int hyst)
{
	struct mlxsw_thermal_module *tz = tzdev->devdata;

	tz->trips[trip].hyst = hyst;
	return 0;
}

static struct thermal_zone_device_ops mlxsw_thermal_module_ops = {
	.bind		= mlxsw_thermal_module_bind,
	.unbind		= mlxsw_thermal_module_unbind,
	.get_temp	= mlxsw_thermal_module_temp_get,
	.get_trip_type	= mlxsw_thermal_module_trip_type_get,
	.get_trip_temp	= mlxsw_thermal_module_trip_temp_get,
	.set_trip_temp	= mlxsw_thermal_module_trip_temp_set,
	.get_trip_hyst	= mlxsw_thermal_module_trip_hyst_get,
	.set_trip_hyst	= mlxsw_thermal_module_trip_hyst_set,
};

static int mlxsw_thermal_gearbox_temp_get(struct thermal_zone_device *tzdev,
@@ -531,11 +415,6 @@ static struct thermal_zone_device_ops mlxsw_thermal_gearbox_ops = {
	.bind		= mlxsw_thermal_module_bind,
	.unbind		= mlxsw_thermal_module_unbind,
	.get_temp	= mlxsw_thermal_gearbox_temp_get,
	.get_trip_type	= mlxsw_thermal_module_trip_type_get,
	.get_trip_temp	= mlxsw_thermal_module_trip_temp_get,
	.set_trip_temp	= mlxsw_thermal_module_trip_temp_set,
	.get_trip_hyst	= mlxsw_thermal_module_trip_hyst_get,
	.set_trip_hyst	= mlxsw_thermal_module_trip_hyst_set,
};

static int mlxsw_thermal_get_max_state(struct thermal_cooling_device *cdev,
@@ -617,7 +496,8 @@ mlxsw_thermal_module_tz_init(struct mlxsw_thermal_module *module_tz)
	else
		snprintf(tz_name, sizeof(tz_name), "mlxsw-module%d",
			 module_tz->module + 1);
	module_tz->tzdev = thermal_zone_device_register(tz_name,
	module_tz->tzdev = thermal_zone_device_register_with_trips(tz_name,
							module_tz->trips,
							MLXSW_THERMAL_NUM_TRIPS,
							MLXSW_THERMAL_TRIP_MASK,
							module_tz,
@@ -661,6 +541,8 @@ mlxsw_thermal_module_init(struct device *dev, struct mlxsw_core *core,
	module_tz->parent = thermal;
	memcpy(module_tz->trips, default_thermal_trips,
	       sizeof(thermal->trips));
	memcpy(module_tz->cooling_states, default_cooling_states,
	       sizeof(thermal->cooling_states));
	/* Initialize all trip point. */
	mlxsw_thermal_module_trips_reset(module_tz);
	/* Read module temperature and thresholds. */
@@ -756,7 +638,8 @@ mlxsw_thermal_gearbox_tz_init(struct mlxsw_thermal_module *gearbox_tz)
	else
		snprintf(tz_name, sizeof(tz_name), "mlxsw-gearbox%d",
			 gearbox_tz->module + 1);
	gearbox_tz->tzdev = thermal_zone_device_register(tz_name,
	gearbox_tz->tzdev = thermal_zone_device_register_with_trips(tz_name,
						gearbox_tz->trips,
						MLXSW_THERMAL_NUM_TRIPS,
						MLXSW_THERMAL_TRIP_MASK,
						gearbox_tz,
@@ -813,6 +696,8 @@ mlxsw_thermal_gearboxes_init(struct device *dev, struct mlxsw_core *core,
		gearbox_tz = &area->tz_gearbox_arr[i];
		memcpy(gearbox_tz->trips, default_thermal_trips,
		       sizeof(thermal->trips));
		memcpy(gearbox_tz->cooling_states, default_cooling_states,
		       sizeof(thermal->cooling_states));
		gearbox_tz->module = i;
		gearbox_tz->parent = thermal;
		gearbox_tz->slot_index = area->slot_index;
@@ -928,6 +813,7 @@ int mlxsw_thermal_init(struct mlxsw_core *core,
	thermal->core = core;
	thermal->bus_info = bus_info;
	memcpy(thermal->trips, default_thermal_trips, sizeof(thermal->trips));
	memcpy(thermal->cooling_states, default_cooling_states, sizeof(thermal->cooling_states));
	thermal->line_cards[0].slot_index = 0;

	err = mlxsw_reg_query(thermal->core, MLXSW_REG(mfcr), mfcr_pl);
@@ -981,7 +867,8 @@ int mlxsw_thermal_init(struct mlxsw_core *core,
				 MLXSW_THERMAL_SLOW_POLL_INT :
				 MLXSW_THERMAL_POLL_INT;

	thermal->tzdev = thermal_zone_device_register("mlxsw",
	thermal->tzdev = thermal_zone_device_register_with_trips("mlxsw",
						      thermal->trips,
						      MLXSW_THERMAL_NUM_TRIPS,
						      MLXSW_THERMAL_TRIP_MASK,
						      thermal,
Loading