1 | // SPDX-License-Identifier: GPL-2.0-only |
2 | /* |
3 | * INT3402 thermal driver for memory temperature reporting |
4 | * |
5 | * Copyright (C) 2014, Intel Corporation |
6 | * Authors: Aaron Lu <aaron.lu@intel.com> |
7 | */ |
8 | |
9 | #include <linux/module.h> |
10 | #include <linux/platform_device.h> |
11 | #include <linux/acpi.h> |
12 | #include <linux/thermal.h> |
13 | #include "int340x_thermal_zone.h" |
14 | |
15 | #define INT3402_PERF_CHANGED_EVENT 0x80 |
16 | #define INT3402_THERMAL_EVENT 0x90 |
17 | |
18 | struct int3402_thermal_data { |
19 | acpi_handle *handle; |
20 | struct int34x_thermal_zone *int340x_zone; |
21 | }; |
22 | |
23 | static void int3402_notify(acpi_handle handle, u32 event, void *data) |
24 | { |
25 | struct int3402_thermal_data *priv = data; |
26 | |
27 | if (!priv) |
28 | return; |
29 | |
30 | switch (event) { |
31 | case INT3402_PERF_CHANGED_EVENT: |
32 | break; |
33 | case INT3402_THERMAL_EVENT: |
34 | int340x_thermal_zone_device_update(tzone: priv->int340x_zone, |
35 | event: THERMAL_TRIP_VIOLATED); |
36 | break; |
37 | default: |
38 | break; |
39 | } |
40 | } |
41 | |
42 | static int int3402_thermal_probe(struct platform_device *pdev) |
43 | { |
44 | struct acpi_device *adev = ACPI_COMPANION(&pdev->dev); |
45 | struct int3402_thermal_data *d; |
46 | int ret; |
47 | |
48 | if (!acpi_has_method(handle: adev->handle, name: "_TMP" )) |
49 | return -ENODEV; |
50 | |
51 | d = devm_kzalloc(dev: &pdev->dev, size: sizeof(*d), GFP_KERNEL); |
52 | if (!d) |
53 | return -ENOMEM; |
54 | |
55 | d->int340x_zone = int340x_thermal_zone_add(adev, NULL); |
56 | if (IS_ERR(ptr: d->int340x_zone)) |
57 | return PTR_ERR(ptr: d->int340x_zone); |
58 | |
59 | ret = acpi_install_notify_handler(device: adev->handle, |
60 | ACPI_DEVICE_NOTIFY, |
61 | handler: int3402_notify, |
62 | context: d); |
63 | if (ret) { |
64 | int340x_thermal_zone_remove(d->int340x_zone); |
65 | return ret; |
66 | } |
67 | |
68 | d->handle = adev->handle; |
69 | platform_set_drvdata(pdev, data: d); |
70 | |
71 | return 0; |
72 | } |
73 | |
74 | static void int3402_thermal_remove(struct platform_device *pdev) |
75 | { |
76 | struct int3402_thermal_data *d = platform_get_drvdata(pdev); |
77 | |
78 | acpi_remove_notify_handler(device: d->handle, |
79 | ACPI_DEVICE_NOTIFY, handler: int3402_notify); |
80 | int340x_thermal_zone_remove(d->int340x_zone); |
81 | } |
82 | |
83 | static const struct acpi_device_id int3402_thermal_match[] = { |
84 | {"INT3402" , 0}, |
85 | {} |
86 | }; |
87 | |
88 | MODULE_DEVICE_TABLE(acpi, int3402_thermal_match); |
89 | |
90 | static struct platform_driver int3402_thermal_driver = { |
91 | .probe = int3402_thermal_probe, |
92 | .remove_new = int3402_thermal_remove, |
93 | .driver = { |
94 | .name = "int3402 thermal" , |
95 | .acpi_match_table = int3402_thermal_match, |
96 | }, |
97 | }; |
98 | |
99 | module_platform_driver(int3402_thermal_driver); |
100 | |
101 | MODULE_DESCRIPTION("INT3402 Thermal driver" ); |
102 | MODULE_LICENSE("GPL" ); |
103 | |