1 /* SPDX-License-Identifier: GPL-2.0-only */
3 #include <acpi/acpigen.h>
5 #include <commonlib/bsd/helpers.h>
6 #include <console/console.h>
7 #include <device/device.h>
13 #define TZ_DEVICE_PATH "\\_TZ"
14 /* These defaults should be good enough for most systems */
17 #define DEFAULT_TSP 10
19 #define CELSIUS_TO_DECI_KELVIN(temp_c) ((temp_c) * 10 + 2732)
20 #define SECONDS_TO_DECI_SECONDS(s) ((s) * 10)
22 static const char *thermal_zone_acpi_name(const struct device
*dev
)
26 if (dev
->path
.type
!= DEVICE_PATH_GENERIC
)
29 name
= malloc(ACPI_NAME_BUFFER_SIZE
);
30 snprintf(name
, ACPI_NAME_BUFFER_SIZE
, "TM%02X", dev
->path
.generic
.id
);
35 static void thermal_zone_fill_ssdt(const struct device
*dev
)
37 struct drivers_acpi_thermal_zone_config
*config
= config_of(dev
);
41 assert(dev
->path
.type
== DEVICE_PATH_GENERIC
);
43 if (config
->use_acpi1_thermal_zone_scope
)
44 scope
= TZ_DEVICE_PATH
;
46 scope
= acpi_device_scope(dev
);
48 name
= acpi_device_name(dev
);
53 if (!config
->temperature_controller
) {
54 printk(BIOS_ERR
, "%s: missing temperature_controller\n", dev_path(dev
));
58 printk(BIOS_INFO
, "%s.%s: %s at %s\n", scope
, name
, dev
->chip_ops
->name
, dev_path(dev
));
60 acpigen_write_scope(scope
);
61 acpigen_write_thermal_zone(name
);
63 if (config
->description
)
64 acpigen_write_name_unicode("_STR", config
->description
);
66 if (config
->polling_period
)
67 acpigen_write_name_integer(
68 "_TZP", SECONDS_TO_DECI_SECONDS(config
->polling_period
));
70 if (config
->critical_temperature
)
71 acpigen_write_name_integer(
72 "_CRT", CELSIUS_TO_DECI_KELVIN(config
->critical_temperature
));
74 if (config
->hibernate_temperature
)
75 acpigen_write_name_integer(
76 "_HOT", CELSIUS_TO_DECI_KELVIN(config
->hibernate_temperature
));
78 if (config
->passive_config
.temperature
) {
79 acpigen_write_name_integer(
80 "_PSV", CELSIUS_TO_DECI_KELVIN(config
->passive_config
.temperature
));
83 * The linux kernel currently has an artificial limit of 10 on the number of
84 * references that can be returned in a list. If we don't respect this limit,
85 * then the passive threshold won't work.
87 * See https://source.chromium.org/chromiumos/chromiumos/codesearch/+/main:src/third_party/kernel/v5.10/include/acpi/acpi_bus.h;l=19
89 acpigen_write_processor_package("_PSL", 0, MIN(10, dev_count_cpu()));
91 acpigen_write_name_integer("_TC1", config
->passive_config
.time_constant_1
93 acpigen_write_name_integer("_TC2", config
->passive_config
.time_constant_2
95 acpigen_write_name_integer(
97 SECONDS_TO_DECI_SECONDS(config
->passive_config
.time_sampling_period
103 * Return (<path>.TMP(<sensor_id>))
106 acpigen_write_method_serialized("_TMP", 0);
107 acpigen_emit_byte(RETURN_OP
);
108 acpigen_emit_namestring(acpi_device_path_join(config
->temperature_controller
, "TMP"));
109 acpigen_write_integer(config
->sensor_id
);
110 acpigen_write_method_end();
112 acpigen_write_thermal_zone_end();
113 acpigen_write_scope_end();
116 static struct device_operations thermal_zone_ops
= {
117 .read_resources
= noop_read_resources
,
118 .set_resources
= noop_set_resources
,
119 .acpi_name
= thermal_zone_acpi_name
,
120 .acpi_fill_ssdt
= thermal_zone_fill_ssdt
,
123 static void thermal_zone_enable_dev(struct device
*dev
)
125 dev
->ops
= &thermal_zone_ops
;
128 struct chip_operations drivers_acpi_thermal_zone_ops
= {
129 .name
= "ACPI Thermal Zone",
130 .enable_dev
= thermal_zone_enable_dev
,