xref: /linux/drivers/hwmon/k10temp.c (revision 570f7e331f5febb30f1384817463c7e42b65ca7d)
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  * k10temp.c - AMD Family 10h/11h/12h/14h/15h/16h/17h
4  *		processor hardware monitoring
5  *
6  * Copyright (c) 2009 Clemens Ladisch <clemens@ladisch.de>
7  * Copyright (c) 2020 Guenter Roeck <linux@roeck-us.net>
8  *
9  * Implementation notes:
10  * - CCD register address information as well as the calculation to
11  *   convert raw register values is from https://github.com/ocerman/zenpower.
12  *   The information is not confirmed from chip datasheets, but experiments
13  *   suggest that it provides reasonable temperature values.
14  */
15 
16 #include <linux/bitops.h>
17 #include <linux/err.h>
18 #include <linux/hwmon.h>
19 #include <linux/init.h>
20 #include <linux/module.h>
21 #include <linux/pci.h>
22 #include <linux/pci_ids.h>
23 
24 #include <asm/amd/node.h>
25 #include <asm/cpuid/api.h>
26 #include <asm/processor.h>
27 
28 MODULE_DESCRIPTION("AMD Family 10h+ CPU core temperature monitor");
29 MODULE_AUTHOR("Clemens Ladisch <clemens@ladisch.de>");
30 MODULE_LICENSE("GPL");
31 
32 static bool force;
33 module_param(force, bool, 0444);
34 MODULE_PARM_DESC(force, "force loading on processors with erratum 319");
35 
36 #ifndef PCI_DEVICE_ID_AMD_15H_M70H_NB_F3
37 #define PCI_DEVICE_ID_AMD_15H_M70H_NB_F3	0x15b3
38 #endif
39 
40 /* CPUID function 0x80000001, ebx */
41 #define CPUID_PKGTYPE_MASK	GENMASK(31, 28)
42 #define CPUID_PKGTYPE_F		0x00000000
43 #define CPUID_PKGTYPE_AM2R2_AM3	0x10000000
44 
45 /* DRAM controller (PCI function 2) */
46 #define REG_DCT0_CONFIG_HIGH		0x094
47 #define  DDR3_MODE			BIT(8)
48 
49 /* miscellaneous (PCI function 3) */
50 #define REG_HARDWARE_THERMAL_CONTROL	0x64
51 #define  HTC_ENABLE			BIT(0)
52 
53 #define REG_REPORTED_TEMPERATURE	0xa4
54 
55 #define REG_NORTHBRIDGE_CAPABILITIES	0xe8
56 #define  NB_CAP_HTC			BIT(10)
57 
58 /*
59  * For F15h M60h and M70h, REG_HARDWARE_THERMAL_CONTROL
60  * and REG_REPORTED_TEMPERATURE have been moved to
61  * D0F0xBC_xD820_0C64 [Hardware Temperature Control]
62  * D0F0xBC_xD820_0CA4 [Reported Temperature Control]
63  */
64 #define F15H_M60H_HARDWARE_TEMP_CTRL_OFFSET	0xd8200c64
65 #define F15H_M60H_REPORTED_TEMP_CTRL_OFFSET	0xd8200ca4
66 
67 /* Common for Zen CPU families (Family 17h and 18h and 19h and 1Ah) */
68 #define ZEN_REPORTED_TEMP_CTRL_BASE		0x00059800
69 
70 #define ZEN_CCD_TEMP(offset, x)			(ZEN_REPORTED_TEMP_CTRL_BASE + \
71 						 (offset) + ((x) * 4))
72 #define ZEN_CCD_TEMP_VALID			BIT(11)
73 #define ZEN_CCD_TEMP_MASK			GENMASK(10, 0)
74 
75 #define ZEN_CUR_TEMP_SHIFT			21
76 #define ZEN_CUR_TEMP_RANGE_SEL_MASK		BIT(19)
77 #define ZEN_CUR_TEMP_TJ_SEL_MASK		GENMASK(17, 16)
78 
79 /*
80  * AMD's Industrial processor 3255 supports temperature from -40 deg to 105 deg Celsius.
81  * Use the model name to identify 3255 CPUs and set a flag to display negative temperature.
82  * Do not round off to zero for negative Tctl or Tdie values if the flag is set
83  */
84 #define AMD_I3255_STR				"3255"
85 
86 /*
87  * PCI Device IDs for AMD's Family 17h-based SOCs.
88  * Defining locally as IDs are not shared.
89  */
90 #define PCI_DEVICE_ID_AMD_17H_M90H_DF_F3	0x1663
91 
92 /*
93  * PCI Device IDs for AMD's Family 1Ah-based SOCs.
94  * Defining locally as IDs are not shared.
95  */
96 #define PCI_DEVICE_ID_AMD_1AH_M50H_DF_F3	0x12cb
97 #define PCI_DEVICE_ID_AMD_1AH_M90H_DF_F3	0x127b
98 
99 struct k10temp_data {
100 	struct pci_dev *pdev;
101 	void (*read_htcreg)(struct pci_dev *pdev, u32 *regval);
102 	void (*read_tempreg)(struct pci_dev *pdev, u32 *regval);
103 	int temp_offset;
104 	u32 temp_adjust_mask;
105 	u32 show_temp;
106 	bool is_zen;
107 	u32 ccd_offset;
108 	bool disp_negative;
109 };
110 
111 #define TCTL_BIT	0
112 #define TDIE_BIT	1
113 #define TCCD_BIT(x)	((x) + 2)
114 
115 #define HAVE_TEMP(d, channel)	((d)->show_temp & BIT(channel))
116 
117 struct tctl_offset {
118 	u8 model;
119 	char const *id;
120 	int offset;
121 };
122 
123 static const struct tctl_offset tctl_offset_table[] = {
124 	{ 0x17, "AMD Ryzen 5 1600X", 20000 },
125 	{ 0x17, "AMD Ryzen 7 1700X", 20000 },
126 	{ 0x17, "AMD Ryzen 7 1800X", 20000 },
127 	{ 0x17, "AMD Ryzen 7 2700X", 10000 },
128 	{ 0x17, "AMD Ryzen Threadripper 19", 27000 }, /* 19{00,20,50}X */
129 	{ 0x17, "AMD Ryzen Threadripper 29", 27000 }, /* 29{20,50,70,90}[W]X */
130 };
131 
132 static void read_htcreg_pci(struct pci_dev *pdev, u32 *regval)
133 {
134 	pci_read_config_dword(pdev, REG_HARDWARE_THERMAL_CONTROL, regval);
135 }
136 
137 static void read_tempreg_pci(struct pci_dev *pdev, u32 *regval)
138 {
139 	pci_read_config_dword(pdev, REG_REPORTED_TEMPERATURE, regval);
140 }
141 
142 static void amd_nb_index_read(struct pci_dev *pdev, unsigned int devfn,
143 			      unsigned int base, int offset, u32 *val)
144 {
145 	pci_bus_write_config_dword(pdev->bus, devfn,
146 				   base, offset);
147 	pci_bus_read_config_dword(pdev->bus, devfn,
148 				  base + 4, val);
149 }
150 
151 static void read_htcreg_nb_f15(struct pci_dev *pdev, u32 *regval)
152 {
153 	amd_nb_index_read(pdev, PCI_DEVFN(0, 0), 0xb8,
154 			  F15H_M60H_HARDWARE_TEMP_CTRL_OFFSET, regval);
155 }
156 
157 static void read_tempreg_nb_f15(struct pci_dev *pdev, u32 *regval)
158 {
159 	amd_nb_index_read(pdev, PCI_DEVFN(0, 0), 0xb8,
160 			  F15H_M60H_REPORTED_TEMP_CTRL_OFFSET, regval);
161 }
162 
163 static u16 amd_pci_dev_to_node_id(struct pci_dev *pdev)
164 {
165 	return PCI_SLOT(pdev->devfn) - AMD_NODE0_PCI_SLOT;
166 }
167 
168 static void read_tempreg_nb_zen(struct pci_dev *pdev, u32 *regval)
169 {
170 	if (amd_smn_read(amd_pci_dev_to_node_id(pdev),
171 			 ZEN_REPORTED_TEMP_CTRL_BASE, regval))
172 		*regval = 0;
173 }
174 
175 static int read_ccd_temp_reg(struct k10temp_data *data, int ccd, u32 *regval)
176 {
177 	u16 node_id = amd_pci_dev_to_node_id(data->pdev);
178 
179 	return amd_smn_read(node_id, ZEN_CCD_TEMP(data->ccd_offset, ccd), regval);
180 }
181 
182 static long get_raw_temp(struct k10temp_data *data)
183 {
184 	u32 regval;
185 	long temp;
186 
187 	data->read_tempreg(data->pdev, &regval);
188 	temp = (regval >> ZEN_CUR_TEMP_SHIFT) * 125;
189 	if ((regval & data->temp_adjust_mask) ||
190 	    (regval & ZEN_CUR_TEMP_TJ_SEL_MASK) == ZEN_CUR_TEMP_TJ_SEL_MASK)
191 		temp -= 49000;
192 	return temp;
193 }
194 
195 static const char *k10temp_temp_label[] = {
196 	"Tctl",
197 	"Tdie",
198 	"Tccd1",
199 	"Tccd2",
200 	"Tccd3",
201 	"Tccd4",
202 	"Tccd5",
203 	"Tccd6",
204 	"Tccd7",
205 	"Tccd8",
206 	"Tccd9",
207 	"Tccd10",
208 	"Tccd11",
209 	"Tccd12",
210 	"Tccd13",
211 	"Tccd14",
212 	"Tccd15",
213 	"Tccd16",
214 };
215 
216 static int k10temp_read_labels(struct device *dev,
217 			       enum hwmon_sensor_types type,
218 			       u32 attr, int channel, const char **str)
219 {
220 	switch (type) {
221 	case hwmon_temp:
222 		*str = k10temp_temp_label[channel];
223 		break;
224 	default:
225 		return -EOPNOTSUPP;
226 	}
227 	return 0;
228 }
229 
230 static int k10temp_read_temp(struct device *dev, u32 attr, int channel,
231 			     long *val)
232 {
233 	struct k10temp_data *data = dev_get_drvdata(dev);
234 	int ret = -EOPNOTSUPP;
235 	u32 regval;
236 
237 	switch (attr) {
238 	case hwmon_temp_input:
239 		switch (channel) {
240 		case 0:		/* Tctl */
241 			*val = get_raw_temp(data);
242 			if (*val < 0 && !data->disp_negative)
243 				*val = 0;
244 			break;
245 		case 1:		/* Tdie */
246 			*val = get_raw_temp(data) - data->temp_offset;
247 			if (*val < 0 && !data->disp_negative)
248 				*val = 0;
249 			break;
250 		case 2 ... 17:		/* Tccd{1-16} */
251 			ret = read_ccd_temp_reg(data, channel - 2, &regval);
252 
253 			if (ret)
254 				return ret;
255 
256 			*val = (regval & ZEN_CCD_TEMP_MASK) * 125 - 49000;
257 			break;
258 		default:
259 			return ret;
260 		}
261 		break;
262 	case hwmon_temp_max:
263 		*val = 70 * 1000;
264 		break;
265 	case hwmon_temp_crit:
266 		data->read_htcreg(data->pdev, &regval);
267 		*val = ((regval >> 16) & 0x7f) * 500 + 52000;
268 		break;
269 	case hwmon_temp_crit_hyst:
270 		data->read_htcreg(data->pdev, &regval);
271 		*val = (((regval >> 16) & 0x7f)
272 			- ((regval >> 24) & 0xf)) * 500 + 52000;
273 		break;
274 	default:
275 		return ret;
276 	}
277 	return 0;
278 }
279 
280 static int k10temp_read(struct device *dev, enum hwmon_sensor_types type,
281 			u32 attr, int channel, long *val)
282 {
283 	switch (type) {
284 	case hwmon_temp:
285 		return k10temp_read_temp(dev, attr, channel, val);
286 	default:
287 		return -EOPNOTSUPP;
288 	}
289 }
290 
291 static umode_t k10temp_is_visible(const void *drvdata,
292 				  enum hwmon_sensor_types type,
293 				  u32 attr, int channel)
294 {
295 	const struct k10temp_data *data = drvdata;
296 	struct pci_dev *pdev = data->pdev;
297 	u32 reg;
298 
299 	switch (type) {
300 	case hwmon_temp:
301 		switch (attr) {
302 		case hwmon_temp_input:
303 			if (!HAVE_TEMP(data, channel))
304 				return 0;
305 			break;
306 		case hwmon_temp_max:
307 			if (channel || data->is_zen)
308 				return 0;
309 			break;
310 		case hwmon_temp_crit:
311 		case hwmon_temp_crit_hyst:
312 			if (channel || !data->read_htcreg)
313 				return 0;
314 
315 			pci_read_config_dword(pdev,
316 					      REG_NORTHBRIDGE_CAPABILITIES,
317 					      &reg);
318 			if (!(reg & NB_CAP_HTC))
319 				return 0;
320 
321 			data->read_htcreg(data->pdev, &reg);
322 			if (!(reg & HTC_ENABLE))
323 				return 0;
324 			break;
325 		case hwmon_temp_label:
326 			/* Show temperature labels only on Zen CPUs */
327 			if (!data->is_zen || !HAVE_TEMP(data, channel))
328 				return 0;
329 			break;
330 		default:
331 			return 0;
332 		}
333 		break;
334 	default:
335 		return 0;
336 	}
337 	return 0444;
338 }
339 
340 static bool has_erratum_319(struct pci_dev *pdev)
341 {
342 	u32 pkg_type, reg_dram_cfg;
343 
344 	if (boot_cpu_data.x86 != 0x10)
345 		return false;
346 
347 	/*
348 	 * Erratum 319: The thermal sensor of Socket F/AM2+ processors
349 	 *              may be unreliable.
350 	 */
351 	pkg_type = cpuid_ebx(0x80000001) & CPUID_PKGTYPE_MASK;
352 	if (pkg_type == CPUID_PKGTYPE_F)
353 		return true;
354 	if (pkg_type != CPUID_PKGTYPE_AM2R2_AM3)
355 		return false;
356 
357 	/* DDR3 memory implies socket AM3, which is good */
358 	pci_bus_read_config_dword(pdev->bus,
359 				  PCI_DEVFN(PCI_SLOT(pdev->devfn), 2),
360 				  REG_DCT0_CONFIG_HIGH, &reg_dram_cfg);
361 	if (reg_dram_cfg & DDR3_MODE)
362 		return false;
363 
364 	/*
365 	 * Unfortunately it is possible to run a socket AM3 CPU with DDR2
366 	 * memory. We blacklist all the cores which do exist in socket AM2+
367 	 * format. It still isn't perfect, as RB-C2 cores exist in both AM2+
368 	 * and AM3 formats, but that's the best we can do.
369 	 */
370 	return boot_cpu_data.x86_model < 4 ||
371 	       (boot_cpu_data.x86_model == 4 && boot_cpu_data.x86_stepping <= 2);
372 }
373 
374 static const struct hwmon_channel_info * const k10temp_info[] = {
375 	HWMON_CHANNEL_INFO(temp,
376 			   HWMON_T_INPUT | HWMON_T_MAX |
377 			   HWMON_T_CRIT | HWMON_T_CRIT_HYST |
378 			   HWMON_T_LABEL,
379 			   HWMON_T_INPUT | HWMON_T_LABEL,
380 			   HWMON_T_INPUT | HWMON_T_LABEL,
381 			   HWMON_T_INPUT | HWMON_T_LABEL,
382 			   HWMON_T_INPUT | HWMON_T_LABEL,
383 			   HWMON_T_INPUT | HWMON_T_LABEL,
384 			   HWMON_T_INPUT | HWMON_T_LABEL,
385 			   HWMON_T_INPUT | HWMON_T_LABEL,
386 			   HWMON_T_INPUT | HWMON_T_LABEL,
387 			   HWMON_T_INPUT | HWMON_T_LABEL,
388 			   HWMON_T_INPUT | HWMON_T_LABEL,
389 			   HWMON_T_INPUT | HWMON_T_LABEL,
390 			   HWMON_T_INPUT | HWMON_T_LABEL,
391 			   HWMON_T_INPUT | HWMON_T_LABEL,
392 			   HWMON_T_INPUT | HWMON_T_LABEL,
393 			   HWMON_T_INPUT | HWMON_T_LABEL,
394 			   HWMON_T_INPUT | HWMON_T_LABEL,
395 			   HWMON_T_INPUT | HWMON_T_LABEL),
396 	NULL
397 };
398 
399 static const struct hwmon_ops k10temp_hwmon_ops = {
400 	.is_visible = k10temp_is_visible,
401 	.read = k10temp_read,
402 	.read_string = k10temp_read_labels,
403 };
404 
405 static const struct hwmon_chip_info k10temp_chip_info = {
406 	.ops = &k10temp_hwmon_ops,
407 	.info = k10temp_info,
408 };
409 
410 static void k10temp_get_ccd_support(struct k10temp_data *data, int limit)
411 {
412 	u32 regval;
413 	int i;
414 
415 	for (i = 0; i < limit; i++) {
416 		/*
417 		 * Ignore inaccessible CCDs.
418 		 *
419 		 * Some systems will return a register value of 0, and the TEMP_VALID
420 		 * bit check below will naturally fail.
421 		 *
422 		 * Other systems will return a PCI_ERROR_RESPONSE (0xFFFFFFFF) for
423 		 * the register value. And this will incorrectly pass the TEMP_VALID
424 		 * bit check.
425 		 */
426 		if (read_ccd_temp_reg(data, i, &regval))
427 			continue;
428 
429 		if (regval & ZEN_CCD_TEMP_VALID)
430 			data->show_temp |= BIT(TCCD_BIT(i));
431 	}
432 }
433 
434 static int k10temp_probe(struct pci_dev *pdev, const struct pci_device_id *id)
435 {
436 	int unreliable = has_erratum_319(pdev);
437 	struct device *dev = &pdev->dev;
438 	struct k10temp_data *data;
439 	struct device *hwmon_dev;
440 	int i;
441 
442 	if (unreliable) {
443 		if (!force) {
444 			dev_err(dev,
445 				"unreliable CPU thermal sensor; monitoring disabled\n");
446 			return -ENODEV;
447 		}
448 		dev_warn(dev,
449 			 "unreliable CPU thermal sensor; check erratum 319\n");
450 	}
451 
452 	data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
453 	if (!data)
454 		return -ENOMEM;
455 
456 	data->pdev = pdev;
457 	data->show_temp |= BIT(TCTL_BIT);	/* Always show Tctl */
458 
459 	if (boot_cpu_data.x86 == 0x17 &&
460 	    strstr(boot_cpu_data.x86_model_id, AMD_I3255_STR)) {
461 		data->disp_negative = true;
462 	}
463 
464 	data->is_zen = cpu_feature_enabled(X86_FEATURE_ZEN);
465 	if (data->is_zen) {
466 		data->temp_adjust_mask = ZEN_CUR_TEMP_RANGE_SEL_MASK;
467 		data->read_tempreg = read_tempreg_nb_zen;
468 	} else if (boot_cpu_data.x86 == 0x15 &&
469 	    ((boot_cpu_data.x86_model & 0xf0) == 0x60 ||
470 	     (boot_cpu_data.x86_model & 0xf0) == 0x70)) {
471 		data->read_htcreg = read_htcreg_nb_f15;
472 		data->read_tempreg = read_tempreg_nb_f15;
473 	} else {
474 		data->read_htcreg = read_htcreg_pci;
475 		data->read_tempreg = read_tempreg_pci;
476 	}
477 
478 	if (boot_cpu_data.x86 == 0x17 || boot_cpu_data.x86 == 0x18) {
479 		switch (boot_cpu_data.x86_model) {
480 		case 0x1:	/* Zen */
481 		case 0x8:	/* Zen+ */
482 		case 0x11:	/* Zen APU */
483 		case 0x18:	/* Zen+ APU */
484 			data->ccd_offset = 0x154;
485 			k10temp_get_ccd_support(data, 4);
486 			break;
487 		case 0x31:	/* Zen2 Threadripper */
488 		case 0x47:	/* Cyan Skillfish */
489 		case 0x60:	/* Renoir */
490 		case 0x68:	/* Lucienne */
491 		case 0x71:	/* Zen2 */
492 			data->ccd_offset = 0x154;
493 			k10temp_get_ccd_support(data, 8);
494 			break;
495 		case 0xa0 ... 0xaf:
496 			data->ccd_offset = 0x300;
497 			k10temp_get_ccd_support(data, 8);
498 			break;
499 		}
500 	} else if (boot_cpu_data.x86 == 0x19) {
501 		switch (boot_cpu_data.x86_model) {
502 		case 0x0 ... 0x1:	/* Zen3 SP3/TR */
503 		case 0x8:		/* Zen3 TR Chagall */
504 		case 0x21:		/* Zen3 Ryzen Desktop */
505 		case 0x50 ... 0x5f:	/* Green Sardine */
506 			data->ccd_offset = 0x154;
507 			k10temp_get_ccd_support(data, 8);
508 			break;
509 		case 0x40 ... 0x4f:	/* Yellow Carp */
510 			data->ccd_offset = 0x300;
511 			k10temp_get_ccd_support(data, 8);
512 			break;
513 		case 0x60 ... 0x6f:
514 		case 0x70 ... 0x7f:
515 			data->ccd_offset = 0x308;
516 			k10temp_get_ccd_support(data, 8);
517 			break;
518 		case 0x10 ... 0x1f:
519 		case 0xa0 ... 0xaf:
520 			data->ccd_offset = 0x300;
521 			k10temp_get_ccd_support(data, 12);
522 			break;
523 		}
524 	} else if (boot_cpu_data.x86 == 0x1a) {
525 		switch (boot_cpu_data.x86_model) {
526 		case 0x00 ... 0x2f:	/* Zen5 Turin */
527 			data->ccd_offset = 0x1F0;
528 			k10temp_get_ccd_support(data, 16);
529 			break;
530 		case 0x40 ... 0x4f:	/* Zen5 Ryzen Desktop */
531 			data->ccd_offset = 0x308;
532 			k10temp_get_ccd_support(data, 8);
533 			break;
534 		}
535 	}
536 
537 	for (i = 0; i < ARRAY_SIZE(tctl_offset_table); i++) {
538 		const struct tctl_offset *entry = &tctl_offset_table[i];
539 
540 		if (boot_cpu_data.x86 == entry->model &&
541 		    strstr(boot_cpu_data.x86_model_id, entry->id)) {
542 			data->show_temp |= BIT(TDIE_BIT);	/* show Tdie */
543 			data->temp_offset = entry->offset;
544 			break;
545 		}
546 	}
547 
548 	hwmon_dev = devm_hwmon_device_register_with_info(dev, "k10temp", data,
549 							 &k10temp_chip_info,
550 							 NULL);
551 	return PTR_ERR_OR_ZERO(hwmon_dev);
552 }
553 
554 static const struct pci_device_id k10temp_id_table[] = {
555 	{ PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_10H_NB_MISC) },
556 	{ PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_11H_NB_MISC) },
557 	{ PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_CNB17H_F3) },
558 	{ PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_15H_NB_F3) },
559 	{ PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_15H_M10H_F3) },
560 	{ PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_15H_M30H_NB_F3) },
561 	{ PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_15H_M60H_NB_F3) },
562 	{ PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_15H_M70H_NB_F3) },
563 	{ PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_16H_NB_F3) },
564 	{ PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_16H_M30H_NB_F3) },
565 	{ PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_17H_DF_F3) },
566 	{ PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_17H_M10H_DF_F3) },
567 	{ PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_17H_M30H_DF_F3) },
568 	{ PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_17H_M40H_DF_F3) },
569 	{ PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_17H_M60H_DF_F3) },
570 	{ PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_17H_M70H_DF_F3) },
571 	{ PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_17H_M90H_DF_F3) },
572 	{ PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_17H_MA0H_DF_F3) },
573 	{ PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_19H_DF_F3) },
574 	{ PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_19H_M10H_DF_F3) },
575 	{ PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_19H_M40H_DF_F3) },
576 	{ PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_19H_M50H_DF_F3) },
577 	{ PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_19H_M60H_DF_F3) },
578 	{ PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_19H_M70H_DF_F3) },
579 	{ PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_19H_M78H_DF_F3) },
580 	{ PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_1AH_M00H_DF_F3) },
581 	{ PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_1AH_M20H_DF_F3) },
582 	{ PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_1AH_M50H_DF_F3) },
583 	{ PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_1AH_M60H_DF_F3) },
584 	{ PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_1AH_M70H_DF_F3) },
585 	{ PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_1AH_M90H_DF_F3) },
586 	{ PCI_VDEVICE(HYGON, PCI_DEVICE_ID_AMD_17H_DF_F3) },
587 	{}
588 };
589 MODULE_DEVICE_TABLE(pci, k10temp_id_table);
590 
591 static struct pci_driver k10temp_driver = {
592 	.name = "k10temp",
593 	.id_table = k10temp_id_table,
594 	.probe = k10temp_probe,
595 };
596 
597 module_pci_driver(k10temp_driver);
598