diff options
author | Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com> | 2016-06-23 18:02:46 -0400 |
---|---|---|
committer | Zhang Rui <rui.zhang@intel.com> | 2016-08-07 22:54:55 -0400 |
commit | 176b1ec21306f0775e6d7a03f42d82a0b144ef0e (patch) | |
tree | d5622c9c0623fb656f8fa4be2820bd7b3e896cd7 | |
parent | 29b4817d4018df78086157ea3a55c1d9424a7cfc (diff) |
thermal: intel_pch_thermal: Add suspend/resume callback
Added suspend/resume callback to disable/enable PCH thermal sensor
respectively. If the sensor is enabled by the BIOS, then the sensor status
will not be changed during suspend/resume.
Signed-off-by: Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>
Signed-off-by: Zhang Rui <rui.zhang@intel.com>
-rw-r--r-- | drivers/thermal/intel_pch_thermal.c | 60 |
1 files changed, 59 insertions, 1 deletions
diff --git a/drivers/thermal/intel_pch_thermal.c b/drivers/thermal/intel_pch_thermal.c index 6a6ec1c95a7a..9b4815e81b0d 100644 --- a/drivers/thermal/intel_pch_thermal.c +++ b/drivers/thermal/intel_pch_thermal.c | |||
@@ -21,6 +21,7 @@ | |||
21 | #include <linux/init.h> | 21 | #include <linux/init.h> |
22 | #include <linux/pci.h> | 22 | #include <linux/pci.h> |
23 | #include <linux/thermal.h> | 23 | #include <linux/thermal.h> |
24 | #include <linux/pm.h> | ||
24 | 25 | ||
25 | /* Intel PCH thermal Device IDs */ | 26 | /* Intel PCH thermal Device IDs */ |
26 | #define PCH_THERMAL_DID_WPT 0x9CA4 /* Wildcat Point */ | 27 | #define PCH_THERMAL_DID_WPT 0x9CA4 /* Wildcat Point */ |
@@ -65,6 +66,7 @@ struct pch_thermal_device { | |||
65 | unsigned long crt_temp; | 66 | unsigned long crt_temp; |
66 | int hot_trip_id; | 67 | int hot_trip_id; |
67 | unsigned long hot_temp; | 68 | unsigned long hot_temp; |
69 | bool bios_enabled; | ||
68 | }; | 70 | }; |
69 | 71 | ||
70 | static int pch_wpt_init(struct pch_thermal_device *ptd, int *nr_trips) | 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 | *nr_trips = 0; | 77 | *nr_trips = 0; |
76 | 78 | ||
77 | /* Check if BIOS has already enabled thermal sensor */ | 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 | goto read_trips; | 82 | goto read_trips; |
83 | } | ||
80 | 84 | ||
81 | tsel = readb(ptd->hw_base + WPT_TSEL); | 85 | tsel = readb(ptd->hw_base + WPT_TSEL); |
82 | /* | 86 | /* |
@@ -130,9 +134,39 @@ static int pch_wpt_get_temp(struct pch_thermal_device *ptd, int *temp) | |||
130 | return 0; | 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 | struct pch_dev_ops { | 165 | struct pch_dev_ops { |
134 | int (*hw_init)(struct pch_thermal_device *ptd, int *nr_trips); | 166 | int (*hw_init)(struct pch_thermal_device *ptd, int *nr_trips); |
135 | int (*get_temp)(struct pch_thermal_device *ptd, int *temp); | 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 | ||
@@ -140,6 +174,8 @@ struct pch_dev_ops { | |||
140 | static const struct pch_dev_ops pch_dev_ops_wpt = { | 174 | static const struct pch_dev_ops pch_dev_ops_wpt = { |
141 | .hw_init = pch_wpt_init, | 175 | .hw_init = pch_wpt_init, |
142 | .get_temp = pch_wpt_get_temp, | 176 | .get_temp = pch_wpt_get_temp, |
177 | .suspend = pch_wpt_suspend, | ||
178 | .resume = pch_wpt_resume, | ||
143 | }; | 179 | }; |
144 | 180 | ||
145 | static int pch_thermal_get_temp(struct thermal_zone_device *tzd, int *temp) | 181 | static int pch_thermal_get_temp(struct thermal_zone_device *tzd, int *temp) |
@@ -269,6 +305,22 @@ static void intel_pch_thermal_remove(struct pci_dev *pdev) | |||
269 | pci_disable_device(pdev); | 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 | static struct pci_device_id intel_pch_thermal_id[] = { | 324 | static struct pci_device_id intel_pch_thermal_id[] = { |
273 | { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCH_THERMAL_DID_WPT) }, | 325 | { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCH_THERMAL_DID_WPT) }, |
274 | { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCH_THERMAL_DID_SKL) }, | 326 | { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCH_THERMAL_DID_SKL) }, |
@@ -276,11 +328,17 @@ static struct pci_device_id intel_pch_thermal_id[] = { | |||
276 | }; | 328 | }; |
277 | MODULE_DEVICE_TABLE(pci, intel_pch_thermal_id); | 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 | static struct pci_driver intel_pch_thermal_driver = { | 336 | static struct pci_driver intel_pch_thermal_driver = { |
280 | .name = "intel_pch_thermal", | 337 | .name = "intel_pch_thermal", |
281 | .id_table = intel_pch_thermal_id, | 338 | .id_table = intel_pch_thermal_id, |
282 | .probe = intel_pch_thermal_probe, | 339 | .probe = intel_pch_thermal_probe, |
283 | .remove = intel_pch_thermal_remove, | 340 | .remove = intel_pch_thermal_remove, |
341 | .driver.pm = &intel_pch_pm_ops, | ||
284 | }; | 342 | }; |
285 | 343 | ||
286 | module_pci_driver(intel_pch_thermal_driver); | 344 | module_pci_driver(intel_pch_thermal_driver); |