1 // SPDX-License-Identifier: GPL-2.0-only
2 /* intel_pch_thermal.c - Intel PCH Thermal driver
3  *
4  * Copyright (c) 2015, Intel Corporation.
5  *
6  * Authors:
7  *     Tushar Dave <tushar.n.dave@intel.com>
8  */
9 
10 #include <linux/acpi.h>
11 #include <linux/delay.h>
12 #include <linux/module.h>
13 #include <linux/init.h>
14 #include <linux/pci.h>
15 #include <linux/pm.h>
16 #include <linux/suspend.h>
17 #include <linux/thermal.h>
18 #include <linux/types.h>
19 #include <linux/units.h>
20 
21 /* Intel PCH thermal Device IDs */
22 #define PCH_THERMAL_DID_HSW_1	0x9C24 /* Haswell PCH */
23 #define PCH_THERMAL_DID_HSW_2	0x8C24 /* Haswell PCH */
24 #define PCH_THERMAL_DID_WPT	0x9CA4 /* Wildcat Point */
25 #define PCH_THERMAL_DID_SKL	0x9D31 /* Skylake PCH */
26 #define PCH_THERMAL_DID_SKL_H	0xA131 /* Skylake PCH 100 series */
27 #define PCH_THERMAL_DID_CNL	0x9Df9 /* CNL PCH */
28 #define PCH_THERMAL_DID_CNL_H	0xA379 /* CNL-H PCH */
29 #define PCH_THERMAL_DID_CNL_LP	0x02F9 /* CNL-LP PCH */
30 #define PCH_THERMAL_DID_CML_H	0X06F9 /* CML-H PCH */
31 
32 /* Wildcat Point-LP  PCH Thermal registers */
33 #define WPT_TEMP	0x0000	/* Temperature */
34 #define WPT_TSC	0x04	/* Thermal Sensor Control */
35 #define WPT_TSS	0x06	/* Thermal Sensor Status */
36 #define WPT_TSEL	0x08	/* Thermal Sensor Enable and Lock */
37 #define WPT_TSREL	0x0A	/* Thermal Sensor Report Enable and Lock */
38 #define WPT_TSMIC	0x0C	/* Thermal Sensor SMI Control */
39 #define WPT_CTT	0x0010	/* Catastrophic Trip Point */
40 #define WPT_TSPM	0x001C	/* Thermal Sensor Power Management */
41 #define WPT_TAHV	0x0014	/* Thermal Alert High Value */
42 #define WPT_TALV	0x0018	/* Thermal Alert Low Value */
43 #define WPT_TL		0x00000040	/* Throttle Value */
44 #define WPT_PHL	0x0060	/* PCH Hot Level */
45 #define WPT_PHLC	0x62	/* PHL Control */
46 #define WPT_TAS	0x80	/* Thermal Alert Status */
47 #define WPT_TSPIEN	0x82	/* PCI Interrupt Event Enables */
48 #define WPT_TSGPEN	0x84	/* General Purpose Event Enables */
49 
50 /*  Wildcat Point-LP  PCH Thermal Register bit definitions */
51 #define WPT_TEMP_TSR	0x01ff	/* Temp TS Reading */
52 #define WPT_TSC_CPDE	0x01	/* Catastrophic Power-Down Enable */
53 #define WPT_TSS_TSDSS	0x10	/* Thermal Sensor Dynamic Shutdown Status */
54 #define WPT_TSS_GPES	0x08	/* GPE status */
55 #define WPT_TSEL_ETS	0x01    /* Enable TS */
56 #define WPT_TSEL_PLDB	0x80	/* TSEL Policy Lock-Down Bit */
57 #define WPT_TL_TOL	0x000001FF	/* T0 Level */
58 #define WPT_TL_T1L	0x1ff00000	/* T1 Level */
59 #define WPT_TL_TTEN	0x20000000	/* TT Enable */
60 
61 /* Resolution of 1/2 degree C and an offset of -50C */
62 #define PCH_TEMP_OFFSET	(-50)
63 #define GET_WPT_TEMP(x)	((x) * MILLIDEGREE_PER_DEGREE / 2 + WPT_TEMP_OFFSET)
64 #define WPT_TEMP_OFFSET	(PCH_TEMP_OFFSET * MILLIDEGREE_PER_DEGREE)
65 #define GET_PCH_TEMP(x)	(((x) / 2) + PCH_TEMP_OFFSET)
66 
67 /* Amount of time for each cooling delay, 100ms by default for now */
68 static unsigned int delay_timeout = 100;
69 module_param(delay_timeout, int, 0644);
70 MODULE_PARM_DESC(delay_timeout, "amount of time delay for each iteration.");
71 
72 /* Number of iterations for cooling delay, 10 counts by default for now */
73 static unsigned int delay_cnt = 10;
74 module_param(delay_cnt, int, 0644);
75 MODULE_PARM_DESC(delay_cnt, "total number of iterations for time delay.");
76 
77 static char driver_name[] = "Intel PCH thermal driver";
78 
79 struct pch_thermal_device {
80 	void __iomem *hw_base;
81 	const struct pch_dev_ops *ops;
82 	struct pci_dev *pdev;
83 	struct thermal_zone_device *tzd;
84 	int crt_trip_id;
85 	unsigned long crt_temp;
86 	int hot_trip_id;
87 	unsigned long hot_temp;
88 	int psv_trip_id;
89 	unsigned long psv_temp;
90 	bool bios_enabled;
91 };
92 
93 #ifdef CONFIG_ACPI
94 
95 /*
96  * On some platforms, there is a companion ACPI device, which adds
97  * passive trip temperature using _PSV method. There is no specific
98  * passive temperature setting in MMIO interface of this PCI device.
99  */
100 static void pch_wpt_add_acpi_psv_trip(struct pch_thermal_device *ptd,
101 				      int *nr_trips)
102 {
103 	struct acpi_device *adev;
104 
105 	ptd->psv_trip_id = -1;
106 
107 	adev = ACPI_COMPANION(&ptd->pdev->dev);
108 	if (adev) {
109 		unsigned long long r;
110 		acpi_status status;
111 
112 		status = acpi_evaluate_integer(adev->handle, "_PSV", NULL,
113 					       &r);
114 		if (ACPI_SUCCESS(status)) {
115 			unsigned long trip_temp;
116 
117 			trip_temp = deci_kelvin_to_millicelsius(r);
118 			if (trip_temp) {
119 				ptd->psv_temp = trip_temp;
120 				ptd->psv_trip_id = *nr_trips;
121 				++(*nr_trips);
122 			}
123 		}
124 	}
125 }
126 #else
127 static void pch_wpt_add_acpi_psv_trip(struct pch_thermal_device *ptd,
128 				      int *nr_trips)
129 {
130 	ptd->psv_trip_id = -1;
131 
132 }
133 #endif
134 
135 static int pch_wpt_init(struct pch_thermal_device *ptd, int *nr_trips)
136 {
137 	u8 tsel;
138 	u16 trip_temp;
139 
140 	*nr_trips = 0;
141 
142 	/* Check if BIOS has already enabled thermal sensor */
143 	if (WPT_TSEL_ETS & readb(ptd->hw_base + WPT_TSEL)) {
144 		ptd->bios_enabled = true;
145 		goto read_trips;
146 	}
147 
148 	tsel = readb(ptd->hw_base + WPT_TSEL);
149 	/*
150 	 * When TSEL's Policy Lock-Down bit is 1, TSEL become RO.
151 	 * If so, thermal sensor cannot enable. Bail out.
152 	 */
153 	if (tsel & WPT_TSEL_PLDB) {
154 		dev_err(&ptd->pdev->dev, "Sensor can't be enabled\n");
155 		return -ENODEV;
156 	}
157 
158 	writeb(tsel|WPT_TSEL_ETS, ptd->hw_base + WPT_TSEL);
159 	if (!(WPT_TSEL_ETS & readb(ptd->hw_base + WPT_TSEL))) {
160 		dev_err(&ptd->pdev->dev, "Sensor can't be enabled\n");
161 		return -ENODEV;
162 	}
163 
164 read_trips:
165 	ptd->crt_trip_id = -1;
166 	trip_temp = readw(ptd->hw_base + WPT_CTT);
167 	trip_temp &= 0x1FF;
168 	if (trip_temp) {
169 		/* Resolution of 1/2 degree C and an offset of -50C */
170 		ptd->crt_temp = trip_temp * 1000 / 2 - 50000;
171 		ptd->crt_trip_id = 0;
172 		++(*nr_trips);
173 	}
174 
175 	ptd->hot_trip_id = -1;
176 	trip_temp = readw(ptd->hw_base + WPT_PHL);
177 	trip_temp &= 0x1FF;
178 	if (trip_temp) {
179 		/* Resolution of 1/2 degree C and an offset of -50C */
180 		ptd->hot_temp = trip_temp * 1000 / 2 - 50000;
181 		ptd->hot_trip_id = *nr_trips;
182 		++(*nr_trips);
183 	}
184 
185 	pch_wpt_add_acpi_psv_trip(ptd, nr_trips);
186 
187 	return 0;
188 }
189 
190 static int pch_wpt_get_temp(struct pch_thermal_device *ptd, int *temp)
191 {
192 	u16 wpt_temp;
193 
194 	wpt_temp = WPT_TEMP_TSR & readw(ptd->hw_base + WPT_TEMP);
195 
196 	/* Resolution of 1/2 degree C and an offset of -50C */
197 	*temp = (wpt_temp * 1000 / 2 - 50000);
198 
199 	return 0;
200 }
201 
202 static int pch_wpt_suspend(struct pch_thermal_device *ptd)
203 {
204 	u8 tsel;
205 	u8 pch_delay_cnt = 1;
206 	u16 pch_thr_temp, pch_cur_temp;
207 
208 	/* Shutdown the thermal sensor if it is not enabled by BIOS */
209 	if (!ptd->bios_enabled) {
210 		tsel = readb(ptd->hw_base + WPT_TSEL);
211 		writeb(tsel & 0xFE, ptd->hw_base + WPT_TSEL);
212 		return 0;
213 	}
214 
215 	/* Do not check temperature if it is not a S0ix capable platform */
216 	if (!(acpi_gbl_FADT.flags & ACPI_FADT_LOW_POWER_S0))
217 		return 0;
218 
219 	/* Do not check temperature if it is not s2idle */
220 	if (pm_suspend_via_firmware())
221 		return 0;
222 
223 	/* Get the PCH temperature threshold value */
224 	pch_thr_temp = GET_PCH_TEMP(WPT_TEMP_TSR & readw(ptd->hw_base + WPT_TSPM));
225 
226 	/* Get the PCH current temperature value */
227 	pch_cur_temp = GET_PCH_TEMP(WPT_TEMP_TSR & readw(ptd->hw_base + WPT_TEMP));
228 
229 	/*
230 	 * If current PCH temperature is higher than configured PCH threshold
231 	 * value, run some delay loop with sleep to let the current temperature
232 	 * go down below the threshold value which helps to allow system enter
233 	 * lower power S0ix suspend state. Even after delay loop if PCH current
234 	 * temperature stays above threshold, notify the warning message
235 	 * which helps to indentify the reason why S0ix entry was rejected.
236 	 */
237 	while (pch_delay_cnt <= delay_cnt) {
238 		if (pch_cur_temp <= pch_thr_temp)
239 			break;
240 
241 		dev_warn(&ptd->pdev->dev,
242 			"CPU-PCH current temp [%dC] higher than the threshold temp [%dC], sleep %d times for %d ms duration\n",
243 			pch_cur_temp, pch_thr_temp, pch_delay_cnt, delay_timeout);
244 		msleep(delay_timeout);
245 		/* Read the PCH current temperature for next cycle. */
246 		pch_cur_temp = GET_PCH_TEMP(WPT_TEMP_TSR & readw(ptd->hw_base + WPT_TEMP));
247 		pch_delay_cnt++;
248 	}
249 
250 	if (pch_cur_temp > pch_thr_temp)
251 		dev_warn(&ptd->pdev->dev,
252 			"CPU-PCH is hot [%dC] even after delay, continue to suspend. S0ix might fail\n",
253 			pch_cur_temp);
254 	else
255 		dev_info(&ptd->pdev->dev,
256 			"CPU-PCH is cool [%dC], continue to suspend\n", pch_cur_temp);
257 
258 	return 0;
259 }
260 
261 static int pch_wpt_resume(struct pch_thermal_device *ptd)
262 {
263 	u8 tsel;
264 
265 	if (ptd->bios_enabled)
266 		return 0;
267 
268 	tsel = readb(ptd->hw_base + WPT_TSEL);
269 
270 	writeb(tsel | WPT_TSEL_ETS, ptd->hw_base + WPT_TSEL);
271 
272 	return 0;
273 }
274 
275 struct pch_dev_ops {
276 	int (*hw_init)(struct pch_thermal_device *ptd, int *nr_trips);
277 	int (*get_temp)(struct pch_thermal_device *ptd, int *temp);
278 	int (*suspend)(struct pch_thermal_device *ptd);
279 	int (*resume)(struct pch_thermal_device *ptd);
280 };
281 
282 
283 /* dev ops for Wildcat Point */
284 static const struct pch_dev_ops pch_dev_ops_wpt = {
285 	.hw_init = pch_wpt_init,
286 	.get_temp = pch_wpt_get_temp,
287 	.suspend = pch_wpt_suspend,
288 	.resume = pch_wpt_resume,
289 };
290 
291 static int pch_thermal_get_temp(struct thermal_zone_device *tzd, int *temp)
292 {
293 	struct pch_thermal_device *ptd = tzd->devdata;
294 
295 	return	ptd->ops->get_temp(ptd, temp);
296 }
297 
298 static int pch_get_trip_type(struct thermal_zone_device *tzd, int trip,
299 			     enum thermal_trip_type *type)
300 {
301 	struct pch_thermal_device *ptd = tzd->devdata;
302 
303 	if (ptd->crt_trip_id == trip)
304 		*type = THERMAL_TRIP_CRITICAL;
305 	else if (ptd->hot_trip_id == trip)
306 		*type = THERMAL_TRIP_HOT;
307 	else if (ptd->psv_trip_id == trip)
308 		*type = THERMAL_TRIP_PASSIVE;
309 	else
310 		return -EINVAL;
311 
312 	return 0;
313 }
314 
315 static int pch_get_trip_temp(struct thermal_zone_device *tzd, int trip, int *temp)
316 {
317 	struct pch_thermal_device *ptd = tzd->devdata;
318 
319 	if (ptd->crt_trip_id == trip)
320 		*temp = ptd->crt_temp;
321 	else if (ptd->hot_trip_id == trip)
322 		*temp = ptd->hot_temp;
323 	else if (ptd->psv_trip_id == trip)
324 		*temp = ptd->psv_temp;
325 	else
326 		return -EINVAL;
327 
328 	return 0;
329 }
330 
331 static struct thermal_zone_device_ops tzd_ops = {
332 	.get_temp = pch_thermal_get_temp,
333 	.get_trip_type = pch_get_trip_type,
334 	.get_trip_temp = pch_get_trip_temp,
335 };
336 
337 enum board_ids {
338 	board_hsw,
339 	board_wpt,
340 	board_skl,
341 	board_cnl,
342 	board_cml,
343 };
344 
345 static const struct board_info {
346 	const char *name;
347 	const struct pch_dev_ops *ops;
348 } board_info[] = {
349 	[board_hsw] = {
350 		.name = "pch_haswell",
351 		.ops = &pch_dev_ops_wpt,
352 	},
353 	[board_wpt] = {
354 		.name = "pch_wildcat_point",
355 		.ops = &pch_dev_ops_wpt,
356 	},
357 	[board_skl] = {
358 		.name = "pch_skylake",
359 		.ops = &pch_dev_ops_wpt,
360 	},
361 	[board_cnl] = {
362 		.name = "pch_cannonlake",
363 		.ops = &pch_dev_ops_wpt,
364 	},
365 	[board_cml] = {
366 		.name = "pch_cometlake",
367 		.ops = &pch_dev_ops_wpt,
368 	}
369 };
370 
371 static int intel_pch_thermal_probe(struct pci_dev *pdev,
372 				   const struct pci_device_id *id)
373 {
374 	enum board_ids board_id = id->driver_data;
375 	const struct board_info *bi = &board_info[board_id];
376 	struct pch_thermal_device *ptd;
377 	int err;
378 	int nr_trips;
379 
380 	ptd = devm_kzalloc(&pdev->dev, sizeof(*ptd), GFP_KERNEL);
381 	if (!ptd)
382 		return -ENOMEM;
383 
384 	ptd->ops = bi->ops;
385 
386 	pci_set_drvdata(pdev, ptd);
387 	ptd->pdev = pdev;
388 
389 	err = pci_enable_device(pdev);
390 	if (err) {
391 		dev_err(&pdev->dev, "failed to enable pci device\n");
392 		return err;
393 	}
394 
395 	err = pci_request_regions(pdev, driver_name);
396 	if (err) {
397 		dev_err(&pdev->dev, "failed to request pci region\n");
398 		goto error_disable;
399 	}
400 
401 	ptd->hw_base = pci_ioremap_bar(pdev, 0);
402 	if (!ptd->hw_base) {
403 		err = -ENOMEM;
404 		dev_err(&pdev->dev, "failed to map mem base\n");
405 		goto error_release;
406 	}
407 
408 	err = ptd->ops->hw_init(ptd, &nr_trips);
409 	if (err)
410 		goto error_cleanup;
411 
412 	ptd->tzd = thermal_zone_device_register(bi->name, nr_trips, 0, ptd,
413 						&tzd_ops, NULL, 0, 0);
414 	if (IS_ERR(ptd->tzd)) {
415 		dev_err(&pdev->dev, "Failed to register thermal zone %s\n",
416 			bi->name);
417 		err = PTR_ERR(ptd->tzd);
418 		goto error_cleanup;
419 	}
420 	err = thermal_zone_device_enable(ptd->tzd);
421 	if (err)
422 		goto err_unregister;
423 
424 	return 0;
425 
426 err_unregister:
427 	thermal_zone_device_unregister(ptd->tzd);
428 error_cleanup:
429 	iounmap(ptd->hw_base);
430 error_release:
431 	pci_release_regions(pdev);
432 error_disable:
433 	pci_disable_device(pdev);
434 	dev_err(&pdev->dev, "pci device failed to probe\n");
435 	return err;
436 }
437 
438 static void intel_pch_thermal_remove(struct pci_dev *pdev)
439 {
440 	struct pch_thermal_device *ptd = pci_get_drvdata(pdev);
441 
442 	thermal_zone_device_unregister(ptd->tzd);
443 	iounmap(ptd->hw_base);
444 	pci_set_drvdata(pdev, NULL);
445 	pci_release_regions(pdev);
446 	pci_disable_device(pdev);
447 }
448 
449 static int intel_pch_thermal_suspend(struct device *device)
450 {
451 	struct pch_thermal_device *ptd = dev_get_drvdata(device);
452 
453 	return ptd->ops->suspend(ptd);
454 }
455 
456 static int intel_pch_thermal_resume(struct device *device)
457 {
458 	struct pch_thermal_device *ptd = dev_get_drvdata(device);
459 
460 	return ptd->ops->resume(ptd);
461 }
462 
463 static const struct pci_device_id intel_pch_thermal_id[] = {
464 	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCH_THERMAL_DID_HSW_1),
465 		.driver_data = board_hsw, },
466 	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCH_THERMAL_DID_HSW_2),
467 		.driver_data = board_hsw, },
468 	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCH_THERMAL_DID_WPT),
469 		.driver_data = board_wpt, },
470 	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCH_THERMAL_DID_SKL),
471 		.driver_data = board_skl, },
472 	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCH_THERMAL_DID_SKL_H),
473 		.driver_data = board_skl, },
474 	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCH_THERMAL_DID_CNL),
475 		.driver_data = board_cnl, },
476 	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCH_THERMAL_DID_CNL_H),
477 		.driver_data = board_cnl, },
478 	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCH_THERMAL_DID_CNL_LP),
479 		.driver_data = board_cnl, },
480 	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCH_THERMAL_DID_CML_H),
481 		.driver_data = board_cml, },
482 	{ 0, },
483 };
484 MODULE_DEVICE_TABLE(pci, intel_pch_thermal_id);
485 
486 static const struct dev_pm_ops intel_pch_pm_ops = {
487 	.suspend = intel_pch_thermal_suspend,
488 	.resume = intel_pch_thermal_resume,
489 };
490 
491 static struct pci_driver intel_pch_thermal_driver = {
492 	.name		= "intel_pch_thermal",
493 	.id_table	= intel_pch_thermal_id,
494 	.probe		= intel_pch_thermal_probe,
495 	.remove		= intel_pch_thermal_remove,
496 	.driver.pm	= &intel_pch_pm_ops,
497 };
498 
499 module_pci_driver(intel_pch_thermal_driver);
500 
501 MODULE_LICENSE("GPL v2");
502 MODULE_DESCRIPTION("Intel PCH Thermal driver");
503