34 #include <linux/kernel.h>
35 #include <linux/module.h>
38 #include <linux/slab.h>
39 #include <linux/types.h>
42 #include <linux/reboot.h>
43 #include <linux/device.h>
44 #include <asm/uaccess.h>
49 #define PREFIX "ACPI: "
51 #define ACPI_THERMAL_CLASS "thermal_zone"
52 #define ACPI_THERMAL_DEVICE_NAME "Thermal Zone"
53 #define ACPI_THERMAL_FILE_STATE "state"
54 #define ACPI_THERMAL_FILE_TEMPERATURE "temperature"
55 #define ACPI_THERMAL_FILE_TRIP_POINTS "trip_points"
56 #define ACPI_THERMAL_FILE_COOLING_MODE "cooling_mode"
57 #define ACPI_THERMAL_FILE_POLLING_FREQ "polling_frequency"
58 #define ACPI_THERMAL_NOTIFY_TEMPERATURE 0x80
59 #define ACPI_THERMAL_NOTIFY_THRESHOLDS 0x81
60 #define ACPI_THERMAL_NOTIFY_DEVICES 0x82
61 #define ACPI_THERMAL_NOTIFY_CRITICAL 0xF0
62 #define ACPI_THERMAL_NOTIFY_HOT 0xF1
63 #define ACPI_THERMAL_MODE_ACTIVE 0x00
65 #define ACPI_THERMAL_MAX_ACTIVE 10
66 #define ACPI_THERMAL_MAX_LIMIT_STR_LEN 65
68 #define _COMPONENT ACPI_THERMAL_COMPONENT
89 MODULE_PARM_DESC(nocrt,
"Set to take no action upon ACPI thermal zone critical trips points.");
99 static int acpi_thermal_add(
struct acpi_device *
device);
100 static int acpi_thermal_remove(
struct acpi_device *
device,
int type);
101 static void acpi_thermal_notify(
struct acpi_device *
device,
u32 event);
109 #ifdef CONFIG_PM_SLEEP
110 static int acpi_thermal_resume(
struct device *
dev);
114 static struct acpi_driver acpi_thermal_driver = {
117 .ids = thermal_device_ids,
119 .add = acpi_thermal_add,
120 .remove = acpi_thermal_remove,
121 .notify = acpi_thermal_notify,
123 .drv.pm = &acpi_thermal_pm,
203 unsigned long long tmp;
221 static int acpi_thermal_get_polling_frequency(
struct acpi_thermal *tz)
224 unsigned long long tmp;
266 #define ACPI_TRIPS_CRITICAL 0x01
267 #define ACPI_TRIPS_HOT 0x02
268 #define ACPI_TRIPS_PASSIVE 0x04
269 #define ACPI_TRIPS_ACTIVE 0x08
270 #define ACPI_TRIPS_DEVICES 0x10
272 #define ACPI_TRIPS_REFRESH_THRESHOLDS (ACPI_TRIPS_PASSIVE | ACPI_TRIPS_ACTIVE)
273 #define ACPI_TRIPS_REFRESH_DEVICES ACPI_TRIPS_DEVICES
275 #define ACPI_TRIPS_INIT (ACPI_TRIPS_CRITICAL | ACPI_TRIPS_HOT | \
276 ACPI_TRIPS_PASSIVE | ACPI_TRIPS_ACTIVE | \
286 #define ACPI_THERMAL_TRIPS_EXCEPTION(flags, str) \
288 if (flags != ACPI_TRIPS_INIT) \
289 ACPI_EXCEPTION((AE_INFO, AE_ERROR, \
290 "ACPI thermal trip point %s changed\n" \
297 unsigned long long tmp;
306 tz->
trips.critical.temperature =
tmp;
314 tz->
trips.critical.flags.valid = 0;
316 "No critical threshold\n"));
317 }
else if (tmp <= 2732) {
320 tz->
trips.critical.flags.valid = 0;
322 tz->
trips.critical.flags.valid = 1;
324 "Found critical threshold [%lu]\n",
325 tz->
trips.critical.temperature));
327 if (tz->
trips.critical.flags.valid == 1) {
329 tz->
trips.critical.flags.valid = 0;
330 }
else if (crt > 0) {
335 if (crt_k > tz->
trips.critical.temperature)
337 "Critical threshold %d C\n", crt);
338 tz->
trips.critical.temperature = crt_k;
348 tz->
trips.hot.flags.valid = 0;
350 "No hot threshold\n"));
353 tz->
trips.hot.flags.valid = 1;
355 "Found hot threshold [%lu]\n",
356 tz->
trips.critical.temperature));
363 valid = tz->
trips.passive.flags.valid;
366 }
else if (psv > 0) {
375 tz->
trips.passive.flags.valid = 0;
377 tz->
trips.passive.temperature =
tmp;
378 tz->
trips.passive.flags.valid = 1;
381 tz->
device->handle,
"_TC1",
384 tz->
trips.passive.flags.valid = 0;
388 tz->
device->handle,
"_TC2",
391 tz->
trips.passive.flags.valid = 0;
395 tz->
device->handle,
"_TSP",
398 tz->
trips.passive.flags.valid = 0;
410 "Invalid passive threshold\n");
411 tz->
trips.passive.flags.valid = 0;
414 tz->
trips.passive.flags.valid = 1;
423 if ((flag & ACPI_TRIPS_PASSIVE) || (flag & ACPI_TRIPS_DEVICES)) {
424 if (valid != tz->
trips.passive.flags.valid)
430 char name[5] = {
'_',
'A',
'C', (
'0' +
i),
'\0' };
431 valid = tz->
trips.active[
i].flags.valid;
437 tz->
trips.active[i].flags.valid)) {
441 tz->
trips.active[
i].flags.valid = 0;
447 tz->
trips.active[0].temperature =
454 tz->
trips.active[i - 1].temperature =
455 (tz->
trips.active[i - 2].temperature <
457 tz->
trips.active[i - 2].temperature :
462 tz->
trips.active[
i].flags.valid = 1;
467 if ((flag & ACPI_TRIPS_DEVICES) && tz->
trips.active[
i].flags.valid ) {
470 name,
NULL, &devices);
473 "Invalid active%d threshold\n", i);
474 tz->
trips.active[
i].flags.valid = 0;
477 tz->
trips.active[
i].flags.valid = 1;
487 if (valid != tz->
trips.active[i].flags.valid)
490 if (!tz->
trips.active[i].flags.valid)
494 if (flag & ACPI_TRIPS_DEVICES) {
509 static int acpi_thermal_get_trip_points(
struct acpi_thermal *tz)
516 valid = tz->
trips.critical.flags.valid |
517 tz->
trips.hot.flags.valid |
518 tz->
trips.passive.flags.valid;
521 valid |= tz->
trips.active[i].flags.valid;
530 static void acpi_thermal_check(
void *
data)
538 #define KELVIN_TO_MILLICELSIUS(t, off) (((t) - (off)) * 100)
549 result = acpi_thermal_get_temperature(tz);
593 "%s kernel ACPI thermal control\n",
595 acpi_thermal_check(tz);
609 if (tz->
trips.critical.flags.valid) {
617 if (tz->
trips.hot.flags.valid) {
625 if (tz->
trips.passive.flags.valid) {
633 for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE &&
634 tz->
trips.active[
i].flags.valid; i++) {
646 int trip,
unsigned long *
temp)
654 if (tz->
trips.critical.flags.valid) {
657 tz->
trips.critical.temperature,
664 if (tz->
trips.hot.flags.valid) {
667 tz->
trips.hot.temperature,
674 if (tz->
trips.passive.flags.valid) {
677 tz->
trips.passive.temperature,
684 for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE &&
685 tz->
trips.active[
i].flags.valid; i++) {
688 tz->
trips.active[i].temperature,
702 if (tz->
trips.critical.flags.valid) {
704 tz->
trips.critical.temperature,
718 if (thermal_get_trip_type(thermal, trip, &type))
732 + (tz->
trips.passive.tc2
758 acpi_bus_generate_proc_event(tz->
device, type, 1);
760 dev_name(&tz->
device->dev), type, 1);
774 struct acpi_device *
dev;
782 if (tz->
trips.critical.flags.valid)
785 if (tz->
trips.hot.flags.valid)
788 if (tz->
trips.passive.flags.valid) {
790 for (i = 0; i < tz->
trips.passive.devices.count;
792 handle = tz->
trips.passive.devices.handles[
i];
799 (thermal, trip, cdev,
804 (thermal, trip, cdev);
811 if (!tz->
trips.active[i].flags.valid)
815 j < tz->
trips.active[
i].devices.count;
817 handle = tz->
trips.active[
i].devices.handles[
j];
823 (thermal, trip, cdev,
827 (thermal, trip, cdev);
833 for (i = 0; i < tz->
devices.count; i++) {
858 return acpi_thermal_cooling_device_cb(thermal, cdev,
true);
865 return acpi_thermal_cooling_device_cb(thermal, cdev,
false);
869 .bind = acpi_thermal_bind_cooling_device,
870 .unbind = acpi_thermal_unbind_cooling_device,
871 .get_temp = thermal_get_temp,
872 .get_mode = thermal_get_mode,
873 .set_mode = thermal_set_mode,
874 .get_trip_type = thermal_get_trip_type,
875 .get_trip_temp = thermal_get_trip_temp,
876 .get_crit_temp = thermal_get_crit_temp,
877 .get_trend = thermal_get_trend,
878 .notify = thermal_notify,
881 static int acpi_thermal_register_thermal_zone(
struct acpi_thermal *tz)
888 if (tz->
trips.critical.flags.valid)
891 if (tz->
trips.hot.flags.valid)
894 if (tz->
trips.passive.flags.valid)
897 for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE &&
898 tz->
trips.active[
i].flags.valid; i++, trips++);
900 if (tz->
trips.passive.flags.valid)
903 &acpi_thermal_zone_ops,
904 tz->
trips.passive.tsp*100,
909 &acpi_thermal_zone_ops, 0,
920 &tz->
device->dev.kobj,
"device");
929 "Error attaching device data\n");
940 static void acpi_thermal_unregister_thermal_zone(
struct acpi_thermal *tz)
954 static void acpi_thermal_notify(
struct acpi_device *device,
u32 event)
964 acpi_thermal_check(tz);
968 acpi_thermal_check(tz);
969 acpi_bus_generate_proc_event(device, event, 0);
971 dev_name(&device->dev), event, 0);
975 acpi_thermal_check(tz);
976 acpi_bus_generate_proc_event(device, event, 0);
978 dev_name(&device->dev), event, 0);
982 "Unsupported event [0x%x]\n", event));
987 static int acpi_thermal_get_info(
struct acpi_thermal *tz)
996 result = acpi_thermal_get_trip_points(tz);
1001 result = acpi_thermal_get_temperature(tz);
1008 tz->
flags.cooling_mode = 1;
1014 acpi_thermal_get_polling_frequency(tz);
1029 static void acpi_thermal_guess_offset(
struct acpi_thermal *tz)
1031 if (tz->
trips.critical.flags.valid &&
1032 (tz->
trips.critical.temperature % 5) == 1)
1038 static int acpi_thermal_add(
struct acpi_device *device)
1055 device->driver_data =
tz;
1059 result = acpi_thermal_get_info(tz);
1063 acpi_thermal_guess_offset(tz);
1065 result = acpi_thermal_register_thermal_zone(tz);
1070 acpi_device_name(device), acpi_device_bid(device),
1080 static int acpi_thermal_remove(
struct acpi_device *device,
int type)
1084 if (!device || !acpi_driver_data(device))
1087 tz = acpi_driver_data(device);
1089 acpi_thermal_unregister_thermal_zone(tz);
1095 #ifdef CONFIG_PM_SLEEP
1096 static int acpi_thermal_resume(
struct device *dev)
1104 tz = acpi_driver_data(to_acpi_device(dev));
1109 if (!(&tz->
trips.active[i]))
1111 if (!tz->
trips.active[i].flags.valid)
1113 tz->
trips.active[
i].flags.enabled = 1;
1114 for (j = 0; j < tz->
trips.active[
i].devices.count; j++) {
1116 tz->
trips.active[i].devices.handles[j],
1119 tz->
trips.active[
i].flags.enabled = 0;
1123 tz->
state.active |= tz->
trips.active[
i].flags.enabled;
1126 acpi_thermal_check(tz);
1136 "disabling all active thermal trip points\n", d->
ident);
1144 "disabling all critical thermal trip point actions.\n", d->
ident);
1152 "enabling thermal zone polling\n", d->
ident);
1161 "disabling all passive thermal trip points\n", d->
ident);
1173 .callback = thermal_act,
1174 .ident =
"AOpen i915GMm-HFS",
1181 .callback = thermal_psv,
1182 .ident =
"AOpen i915GMm-HFS",
1189 .callback = thermal_tzp,
1190 .ident =
"AOpen i915GMm-HFS",
1197 .callback = thermal_nocrt,
1198 .ident =
"Gigabyte GA-7ZX",
1207 static int __init acpi_thermal_init(
void)
1225 static void __exit acpi_thermal_exit(
void)