1// SPDX-License-Identifier: GPL-2.0-only
2/*
3 * Processor thermal device for newer processors
4 * Copyright (c) 2020, Intel Corporation.
5 */
6
7#include <linux/acpi.h>
8#include <linux/kernel.h>
9#include <linux/module.h>
10#include <linux/pci.h>
11#include <linux/thermal.h>
12
13#include "int340x_thermal_zone.h"
14#include "processor_thermal_device.h"
15
16#define DRV_NAME "proc_thermal_pci"
17
18static bool use_msi;
19module_param(use_msi, bool, 0644);
20MODULE_PARM_DESC(use_msi,
21	"Use PCI MSI based interrupts for processor thermal device.");
22
23struct proc_thermal_pci {
24	struct pci_dev *pdev;
25	struct proc_thermal_device *proc_priv;
26	struct thermal_zone_device *tzone;
27	struct delayed_work work;
28	int stored_thres;
29	int no_legacy;
30};
31
32enum proc_thermal_mmio_type {
33	PROC_THERMAL_MMIO_TJMAX,
34	PROC_THERMAL_MMIO_PP0_TEMP,
35	PROC_THERMAL_MMIO_PP1_TEMP,
36	PROC_THERMAL_MMIO_PKG_TEMP,
37	PROC_THERMAL_MMIO_THRES_0,
38	PROC_THERMAL_MMIO_THRES_1,
39	PROC_THERMAL_MMIO_INT_ENABLE_0,
40	PROC_THERMAL_MMIO_INT_ENABLE_1,
41	PROC_THERMAL_MMIO_INT_STATUS_0,
42	PROC_THERMAL_MMIO_INT_STATUS_1,
43	PROC_THERMAL_MMIO_MAX
44};
45
46struct proc_thermal_mmio_info {
47	enum proc_thermal_mmio_type mmio_type;
48	u64	mmio_addr;
49	u64	shift;
50	u64	mask;
51};
52
53static struct proc_thermal_mmio_info proc_thermal_mmio_info[] = {
54	{ PROC_THERMAL_MMIO_TJMAX, 0x599c, 16, 0xff },
55	{ PROC_THERMAL_MMIO_PP0_TEMP, 0x597c, 0, 0xff },
56	{ PROC_THERMAL_MMIO_PP1_TEMP, 0x5980, 0, 0xff },
57	{ PROC_THERMAL_MMIO_PKG_TEMP, 0x5978, 0, 0xff },
58	{ PROC_THERMAL_MMIO_THRES_0, 0x5820, 8, 0x7F },
59	{ PROC_THERMAL_MMIO_THRES_1, 0x5820, 16, 0x7F },
60	{ PROC_THERMAL_MMIO_INT_ENABLE_0, 0x5820, 15, 0x01 },
61	{ PROC_THERMAL_MMIO_INT_ENABLE_1, 0x5820, 23, 0x01 },
62	{ PROC_THERMAL_MMIO_INT_STATUS_0, 0x7200, 6, 0x01 },
63	{ PROC_THERMAL_MMIO_INT_STATUS_1, 0x7200, 8, 0x01 },
64};
65
66#define B0D4_THERMAL_NOTIFY_DELAY	1000
67static int notify_delay_ms = B0D4_THERMAL_NOTIFY_DELAY;
68
69static void proc_thermal_mmio_read(struct proc_thermal_pci *pci_info,
70				    enum proc_thermal_mmio_type type,
71				    u32 *value)
72{
73	*value = ioread32(((u8 __iomem *)pci_info->proc_priv->mmio_base +
74				proc_thermal_mmio_info[type].mmio_addr));
75	*value >>= proc_thermal_mmio_info[type].shift;
76	*value &= proc_thermal_mmio_info[type].mask;
77}
78
79static void proc_thermal_mmio_write(struct proc_thermal_pci *pci_info,
80				     enum proc_thermal_mmio_type type,
81				     u32 value)
82{
83	u32 current_val;
84	u32 mask;
85
86	current_val = ioread32(((u8 __iomem *)pci_info->proc_priv->mmio_base +
87				proc_thermal_mmio_info[type].mmio_addr));
88	mask = proc_thermal_mmio_info[type].mask << proc_thermal_mmio_info[type].shift;
89	current_val &= ~mask;
90
91	value &= proc_thermal_mmio_info[type].mask;
92	value <<= proc_thermal_mmio_info[type].shift;
93
94	current_val |= value;
95	iowrite32(current_val, ((u8 __iomem *)pci_info->proc_priv->mmio_base +
96				proc_thermal_mmio_info[type].mmio_addr));
97}
98
99/*
100 * To avoid sending two many messages to user space, we have 1 second delay.
101 * On interrupt we are disabling interrupt and enabling after 1 second.
102 * This workload function is delayed by 1 second.
103 */
104static void proc_thermal_threshold_work_fn(struct work_struct *work)
105{
106	struct delayed_work *delayed_work = to_delayed_work(work);
107	struct proc_thermal_pci *pci_info = container_of(delayed_work,
108						struct proc_thermal_pci, work);
109	struct thermal_zone_device *tzone = pci_info->tzone;
110
111	if (tzone)
112		thermal_zone_device_update(tzone, THERMAL_TRIP_VIOLATED);
113
114	/* Enable interrupt flag */
115	proc_thermal_mmio_write(pci_info, PROC_THERMAL_MMIO_INT_ENABLE_0, 1);
116}
117
118static void pkg_thermal_schedule_work(struct delayed_work *work)
119{
120	unsigned long ms = msecs_to_jiffies(notify_delay_ms);
121
122	schedule_delayed_work(work, ms);
123}
124
125static void proc_thermal_clear_soc_int_status(struct proc_thermal_device *proc_priv)
126{
127	u64 status;
128
129	if (!(proc_priv->mmio_feature_mask &
130	    (PROC_THERMAL_FEATURE_WT_HINT | PROC_THERMAL_FEATURE_POWER_FLOOR)))
131		return;
132
133	status = readq(proc_priv->mmio_base + SOC_WT_RES_INT_STATUS_OFFSET);
134	writeq(status & ~SOC_WT_RES_INT_STATUS_MASK,
135	       proc_priv->mmio_base + SOC_WT_RES_INT_STATUS_OFFSET);
136}
137
138static irqreturn_t proc_thermal_irq_thread_handler(int irq, void *devid)
139{
140	struct proc_thermal_pci *pci_info = devid;
141
142	proc_thermal_wt_intr_callback(pci_info->pdev, pci_info->proc_priv);
143	proc_thermal_power_floor_intr_callback(pci_info->pdev, pci_info->proc_priv);
144	proc_thermal_clear_soc_int_status(pci_info->proc_priv);
145
146	return IRQ_HANDLED;
147}
148
149static irqreturn_t proc_thermal_irq_handler(int irq, void *devid)
150{
151	struct proc_thermal_pci *pci_info = devid;
152	struct proc_thermal_device *proc_priv;
153	int ret = IRQ_HANDLED;
154	u32 status;
155
156	proc_priv = pci_info->proc_priv;
157
158	if (proc_priv->mmio_feature_mask & PROC_THERMAL_FEATURE_WT_HINT) {
159		if (proc_thermal_check_wt_intr(pci_info->proc_priv))
160			ret = IRQ_WAKE_THREAD;
161	}
162
163	if (proc_priv->mmio_feature_mask & PROC_THERMAL_FEATURE_POWER_FLOOR) {
164		if (proc_thermal_check_power_floor_intr(pci_info->proc_priv))
165			ret = IRQ_WAKE_THREAD;
166	}
167
168	/*
169	 * Since now there are two sources of interrupts: one from thermal threshold
170	 * and another from workload hint, add a check if there was really a threshold
171	 * interrupt before scheduling work function for thermal threshold.
172	 */
173	proc_thermal_mmio_read(pci_info, PROC_THERMAL_MMIO_INT_STATUS_0, &status);
174	if (status) {
175		/* Disable enable interrupt flag */
176		proc_thermal_mmio_write(pci_info, PROC_THERMAL_MMIO_INT_ENABLE_0, 0);
177		pkg_thermal_schedule_work(&pci_info->work);
178	}
179
180	pci_write_config_byte(pci_info->pdev, 0xdc, 0x01);
181
182	return ret;
183}
184
185static int sys_get_curr_temp(struct thermal_zone_device *tzd, int *temp)
186{
187	struct proc_thermal_pci *pci_info = thermal_zone_device_priv(tzd);
188	u32 _temp;
189
190	proc_thermal_mmio_read(pci_info, PROC_THERMAL_MMIO_PKG_TEMP, &_temp);
191	*temp = (unsigned long)_temp * 1000;
192
193	return 0;
194}
195
196static int sys_set_trip_temp(struct thermal_zone_device *tzd, int trip, int temp)
197{
198	struct proc_thermal_pci *pci_info = thermal_zone_device_priv(tzd);
199	int tjmax, _temp;
200
201	if (temp <= 0) {
202		cancel_delayed_work_sync(&pci_info->work);
203		proc_thermal_mmio_write(pci_info, PROC_THERMAL_MMIO_INT_ENABLE_0, 0);
204		proc_thermal_mmio_write(pci_info, PROC_THERMAL_MMIO_THRES_0, 0);
205		pci_info->stored_thres = 0;
206		return 0;
207	}
208
209	proc_thermal_mmio_read(pci_info, PROC_THERMAL_MMIO_TJMAX, &tjmax);
210	_temp = tjmax - (temp / 1000);
211	if (_temp < 0)
212		return -EINVAL;
213
214	proc_thermal_mmio_write(pci_info, PROC_THERMAL_MMIO_THRES_0, _temp);
215	proc_thermal_mmio_write(pci_info, PROC_THERMAL_MMIO_INT_ENABLE_0, 1);
216
217	pci_info->stored_thres = temp;
218
219	return 0;
220}
221
222static int get_trip_temp(struct proc_thermal_pci *pci_info)
223{
224	int temp, tjmax;
225
226	proc_thermal_mmio_read(pci_info, PROC_THERMAL_MMIO_THRES_0, &temp);
227	if (!temp)
228		return THERMAL_TEMP_INVALID;
229
230	proc_thermal_mmio_read(pci_info, PROC_THERMAL_MMIO_TJMAX, &tjmax);
231	temp = (tjmax - temp) * 1000;
232
233	return temp;
234}
235
236static const struct thermal_zone_device_ops tzone_ops = {
237	.get_temp = sys_get_curr_temp,
238	.set_trip_temp	= sys_set_trip_temp,
239};
240
241static struct thermal_zone_params tzone_params = {
242	.governor_name = "user_space",
243	.no_hwmon = true,
244};
245
246static int proc_thermal_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
247{
248	struct proc_thermal_device *proc_priv;
249	struct proc_thermal_pci *pci_info;
250	struct thermal_trip psv_trip = {
251		.type = THERMAL_TRIP_PASSIVE,
252		.flags = THERMAL_TRIP_FLAG_RW_TEMP,
253	};
254	int irq_flag = 0, irq, ret;
255	bool msi_irq = false;
256
257	proc_priv = devm_kzalloc(&pdev->dev, sizeof(*proc_priv), GFP_KERNEL);
258	if (!proc_priv)
259		return -ENOMEM;
260
261	pci_info = devm_kzalloc(&pdev->dev, sizeof(*pci_info), GFP_KERNEL);
262	if (!pci_info)
263		return -ENOMEM;
264
265	pci_info->pdev = pdev;
266	ret = pcim_enable_device(pdev);
267	if (ret < 0) {
268		dev_err(&pdev->dev, "error: could not enable device\n");
269		return ret;
270	}
271
272	pci_set_master(pdev);
273
274	INIT_DELAYED_WORK(&pci_info->work, proc_thermal_threshold_work_fn);
275
276	proc_priv->priv_data = pci_info;
277	pci_info->proc_priv = proc_priv;
278	pci_set_drvdata(pdev, proc_priv);
279
280	ret = proc_thermal_mmio_add(pdev, proc_priv, id->driver_data);
281	if (ret)
282		return ret;
283
284	ret = proc_thermal_add(&pdev->dev, proc_priv);
285	if (ret) {
286		dev_err(&pdev->dev, "error: proc_thermal_add, will continue\n");
287		pci_info->no_legacy = 1;
288	}
289
290	psv_trip.temperature = get_trip_temp(pci_info);
291
292	pci_info->tzone = thermal_zone_device_register_with_trips("TCPU_PCI", &psv_trip,
293							1, pci_info,
294							&tzone_ops,
295							&tzone_params, 0, 0);
296	if (IS_ERR(pci_info->tzone)) {
297		ret = PTR_ERR(pci_info->tzone);
298		goto err_del_legacy;
299	}
300
301	if (use_msi && (pdev->msi_enabled || pdev->msix_enabled)) {
302		/* request and enable interrupt */
303		ret = pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_ALL_TYPES);
304		if (ret < 0) {
305			dev_err(&pdev->dev, "Failed to allocate vectors!\n");
306			goto err_ret_tzone;
307		}
308
309		irq =  pci_irq_vector(pdev, 0);
310		msi_irq = true;
311	} else {
312		irq_flag = IRQF_SHARED;
313		irq = pdev->irq;
314	}
315
316	ret = devm_request_threaded_irq(&pdev->dev, irq,
317					proc_thermal_irq_handler, proc_thermal_irq_thread_handler,
318					irq_flag, KBUILD_MODNAME, pci_info);
319	if (ret) {
320		dev_err(&pdev->dev, "Request IRQ %d failed\n", pdev->irq);
321		goto err_free_vectors;
322	}
323
324	ret = thermal_zone_device_enable(pci_info->tzone);
325	if (ret)
326		goto err_free_vectors;
327
328	return 0;
329
330err_free_vectors:
331	if (msi_irq)
332		pci_free_irq_vectors(pdev);
333err_ret_tzone:
334	thermal_zone_device_unregister(pci_info->tzone);
335err_del_legacy:
336	if (!pci_info->no_legacy)
337		proc_thermal_remove(proc_priv);
338	proc_thermal_mmio_remove(pdev, proc_priv);
339	pci_disable_device(pdev);
340
341	return ret;
342}
343
344static void proc_thermal_pci_remove(struct pci_dev *pdev)
345{
346	struct proc_thermal_device *proc_priv = pci_get_drvdata(pdev);
347	struct proc_thermal_pci *pci_info = proc_priv->priv_data;
348
349	cancel_delayed_work_sync(&pci_info->work);
350
351	proc_thermal_mmio_write(pci_info, PROC_THERMAL_MMIO_THRES_0, 0);
352	proc_thermal_mmio_write(pci_info, PROC_THERMAL_MMIO_INT_ENABLE_0, 0);
353
354	devm_free_irq(&pdev->dev, pdev->irq, pci_info);
355	pci_free_irq_vectors(pdev);
356
357	thermal_zone_device_unregister(pci_info->tzone);
358	proc_thermal_mmio_remove(pdev, pci_info->proc_priv);
359	if (!pci_info->no_legacy)
360		proc_thermal_remove(proc_priv);
361	pci_disable_device(pdev);
362}
363
364#ifdef CONFIG_PM_SLEEP
365static int proc_thermal_pci_suspend(struct device *dev)
366{
367	struct pci_dev *pdev = to_pci_dev(dev);
368	struct proc_thermal_device *proc_priv;
369	struct proc_thermal_pci *pci_info;
370
371	proc_priv = pci_get_drvdata(pdev);
372	pci_info = proc_priv->priv_data;
373
374	if (!pci_info->no_legacy)
375		return proc_thermal_suspend(dev);
376
377	return 0;
378}
379static int proc_thermal_pci_resume(struct device *dev)
380{
381	struct pci_dev *pdev = to_pci_dev(dev);
382	struct proc_thermal_device *proc_priv;
383	struct proc_thermal_pci *pci_info;
384
385	proc_priv = pci_get_drvdata(pdev);
386	pci_info = proc_priv->priv_data;
387
388	if (pci_info->stored_thres) {
389		proc_thermal_mmio_write(pci_info, PROC_THERMAL_MMIO_THRES_0,
390					 pci_info->stored_thres / 1000);
391		proc_thermal_mmio_write(pci_info, PROC_THERMAL_MMIO_INT_ENABLE_0, 1);
392	}
393
394	if (!pci_info->no_legacy)
395		return proc_thermal_resume(dev);
396
397	return 0;
398}
399#else
400#define proc_thermal_pci_suspend NULL
401#define proc_thermal_pci_resume NULL
402#endif
403
404static SIMPLE_DEV_PM_OPS(proc_thermal_pci_pm, proc_thermal_pci_suspend,
405			 proc_thermal_pci_resume);
406
407static const struct pci_device_id proc_thermal_pci_ids[] = {
408	{ PCI_DEVICE_DATA(INTEL, ADL_THERMAL, PROC_THERMAL_FEATURE_RAPL |
409	  PROC_THERMAL_FEATURE_FIVR | PROC_THERMAL_FEATURE_DVFS | PROC_THERMAL_FEATURE_WT_REQ) },
410	{ PCI_DEVICE_DATA(INTEL, LNLM_THERMAL, PROC_THERMAL_FEATURE_RAPL) },
411	{ PCI_DEVICE_DATA(INTEL, MTLP_THERMAL, PROC_THERMAL_FEATURE_RAPL |
412	  PROC_THERMAL_FEATURE_FIVR | PROC_THERMAL_FEATURE_DVFS | PROC_THERMAL_FEATURE_DLVR |
413	  PROC_THERMAL_FEATURE_WT_HINT | PROC_THERMAL_FEATURE_POWER_FLOOR) },
414	{ PCI_DEVICE_DATA(INTEL, ARL_S_THERMAL, PROC_THERMAL_FEATURE_RAPL |
415	  PROC_THERMAL_FEATURE_DVFS | PROC_THERMAL_FEATURE_DLVR | PROC_THERMAL_FEATURE_WT_HINT) },
416	{ PCI_DEVICE_DATA(INTEL, RPL_THERMAL, PROC_THERMAL_FEATURE_RAPL |
417	  PROC_THERMAL_FEATURE_FIVR | PROC_THERMAL_FEATURE_DVFS | PROC_THERMAL_FEATURE_WT_REQ) },
418	{ },
419};
420
421MODULE_DEVICE_TABLE(pci, proc_thermal_pci_ids);
422
423static struct pci_driver proc_thermal_pci_driver = {
424	.name		= DRV_NAME,
425	.probe		= proc_thermal_pci_probe,
426	.remove	= proc_thermal_pci_remove,
427	.id_table	= proc_thermal_pci_ids,
428	.driver.pm	= &proc_thermal_pci_pm,
429};
430
431module_pci_driver(proc_thermal_pci_driver);
432
433MODULE_IMPORT_NS(INT340X_THERMAL);
434
435MODULE_AUTHOR("Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>");
436MODULE_DESCRIPTION("Processor Thermal Reporting Device Driver");
437MODULE_LICENSE("GPL v2");
438