21
21
#include <linux/init.h>
22
22
#include <linux/pci.h>
23
23
#include <linux/thermal.h>
24
+ #include <linux/pm.h>
24
25
25
26
/* Intel PCH thermal Device IDs */
26
27
#define PCH_THERMAL_DID_WPT 0x9CA4 /* Wildcat Point */
@@ -65,6 +66,7 @@ struct pch_thermal_device {
65
66
unsigned long crt_temp ;
66
67
int hot_trip_id ;
67
68
unsigned long hot_temp ;
69
+ bool bios_enabled ;
68
70
};
69
71
70
72
static int pch_wpt_init (struct pch_thermal_device * ptd , int * nr_trips )
@@ -75,8 +77,10 @@ static int pch_wpt_init(struct pch_thermal_device *ptd, int *nr_trips)
75
77
* nr_trips = 0 ;
76
78
77
79
/* Check if BIOS has already enabled thermal sensor */
78
- if (WPT_TSS_TSDSS & readb (ptd -> hw_base + WPT_TSS ))
80
+ if (WPT_TSS_TSDSS & readb (ptd -> hw_base + WPT_TSS )) {
81
+ ptd -> bios_enabled = true;
79
82
goto read_trips ;
83
+ }
80
84
81
85
tsel = readb (ptd -> hw_base + WPT_TSEL );
82
86
/*
@@ -130,16 +134,48 @@ static int pch_wpt_get_temp(struct pch_thermal_device *ptd, int *temp)
130
134
return 0 ;
131
135
}
132
136
137
+ static int pch_wpt_suspend (struct pch_thermal_device * ptd )
138
+ {
139
+ u8 tsel ;
140
+
141
+ if (ptd -> bios_enabled )
142
+ return 0 ;
143
+
144
+ tsel = readb (ptd -> hw_base + WPT_TSEL );
145
+
146
+ writeb (tsel & 0xFE , ptd -> hw_base + WPT_TSEL );
147
+
148
+ return 0 ;
149
+ }
150
+
151
+ static int pch_wpt_resume (struct pch_thermal_device * ptd )
152
+ {
153
+ u8 tsel ;
154
+
155
+ if (ptd -> bios_enabled )
156
+ return 0 ;
157
+
158
+ tsel = readb (ptd -> hw_base + WPT_TSEL );
159
+
160
+ writeb (tsel | WPT_TSEL_ETS , ptd -> hw_base + WPT_TSEL );
161
+
162
+ return 0 ;
163
+ }
164
+
133
165
struct pch_dev_ops {
134
166
int (* hw_init )(struct pch_thermal_device * ptd , int * nr_trips );
135
167
int (* get_temp )(struct pch_thermal_device * ptd , int * temp );
168
+ int (* suspend )(struct pch_thermal_device * ptd );
169
+ int (* resume )(struct pch_thermal_device * ptd );
136
170
};
137
171
138
172
139
173
/* dev ops for Wildcat Point */
140
174
static const struct pch_dev_ops pch_dev_ops_wpt = {
141
175
.hw_init = pch_wpt_init ,
142
176
.get_temp = pch_wpt_get_temp ,
177
+ .suspend = pch_wpt_suspend ,
178
+ .resume = pch_wpt_resume ,
143
179
};
144
180
145
181
static int pch_thermal_get_temp (struct thermal_zone_device * tzd , int * temp )
@@ -269,18 +305,40 @@ static void intel_pch_thermal_remove(struct pci_dev *pdev)
269
305
pci_disable_device (pdev );
270
306
}
271
307
308
+ static int intel_pch_thermal_suspend (struct device * device )
309
+ {
310
+ struct pci_dev * pdev = to_pci_dev (device );
311
+ struct pch_thermal_device * ptd = pci_get_drvdata (pdev );
312
+
313
+ return ptd -> ops -> suspend (ptd );
314
+ }
315
+
316
+ static int intel_pch_thermal_resume (struct device * device )
317
+ {
318
+ struct pci_dev * pdev = to_pci_dev (device );
319
+ struct pch_thermal_device * ptd = pci_get_drvdata (pdev );
320
+
321
+ return ptd -> ops -> resume (ptd );
322
+ }
323
+
272
324
static struct pci_device_id intel_pch_thermal_id [] = {
273
325
{ PCI_DEVICE (PCI_VENDOR_ID_INTEL , PCH_THERMAL_DID_WPT ) },
274
326
{ PCI_DEVICE (PCI_VENDOR_ID_INTEL , PCH_THERMAL_DID_SKL ) },
275
327
{ 0 , },
276
328
};
277
329
MODULE_DEVICE_TABLE (pci , intel_pch_thermal_id );
278
330
331
+ static const struct dev_pm_ops intel_pch_pm_ops = {
332
+ .suspend = intel_pch_thermal_suspend ,
333
+ .resume = intel_pch_thermal_resume ,
334
+ };
335
+
279
336
static struct pci_driver intel_pch_thermal_driver = {
280
337
.name = "intel_pch_thermal" ,
281
338
.id_table = intel_pch_thermal_id ,
282
339
.probe = intel_pch_thermal_probe ,
283
340
.remove = intel_pch_thermal_remove ,
341
+ .driver .pm = & intel_pch_pm_ops ,
284
342
};
285
343
286
344
module_pci_driver (intel_pch_thermal_driver );
0 commit comments