1b5d3c728SJuergen Gross // SPDX-License-Identifier: GPL-2.0-only
2b5d3c728SJuergen Gross
3b5d3c728SJuergen Gross #include <linux/types.h>
4*961c6a43SJuergen Gross #include <linux/slab.h>
5b5d3c728SJuergen Gross #include <linux/syscore_ops.h>
6b5d3c728SJuergen Gross #include <asm/cpufeature.h>
7b5d3c728SJuergen Gross #include <asm/mtrr.h>
8b5d3c728SJuergen Gross #include <asm/processor.h>
9b5d3c728SJuergen Gross #include "mtrr.h"
10b5d3c728SJuergen Gross
mtrr_set_if(void)11b5d3c728SJuergen Gross void mtrr_set_if(void)
12b5d3c728SJuergen Gross {
13b5d3c728SJuergen Gross switch (boot_cpu_data.x86_vendor) {
14b5d3c728SJuergen Gross case X86_VENDOR_AMD:
15b5d3c728SJuergen Gross /* Pre-Athlon (K6) AMD CPU MTRRs */
16b5d3c728SJuergen Gross if (cpu_feature_enabled(X86_FEATURE_K6_MTRR))
17b5d3c728SJuergen Gross mtrr_if = &amd_mtrr_ops;
18b5d3c728SJuergen Gross break;
19b5d3c728SJuergen Gross case X86_VENDOR_CENTAUR:
20b5d3c728SJuergen Gross if (cpu_feature_enabled(X86_FEATURE_CENTAUR_MCR))
21b5d3c728SJuergen Gross mtrr_if = ¢aur_mtrr_ops;
22b5d3c728SJuergen Gross break;
23b5d3c728SJuergen Gross case X86_VENDOR_CYRIX:
24b5d3c728SJuergen Gross if (cpu_feature_enabled(X86_FEATURE_CYRIX_ARR))
25b5d3c728SJuergen Gross mtrr_if = &cyrix_mtrr_ops;
26b5d3c728SJuergen Gross break;
27b5d3c728SJuergen Gross default:
28b5d3c728SJuergen Gross break;
29b5d3c728SJuergen Gross }
30b5d3c728SJuergen Gross }
31b5d3c728SJuergen Gross
32b5d3c728SJuergen Gross /*
33b5d3c728SJuergen Gross * The suspend/resume methods are only for CPUs without MTRR. CPUs using generic
34b5d3c728SJuergen Gross * MTRR driver don't require this.
35b5d3c728SJuergen Gross */
36b5d3c728SJuergen Gross struct mtrr_value {
37b5d3c728SJuergen Gross mtrr_type ltype;
38b5d3c728SJuergen Gross unsigned long lbase;
39b5d3c728SJuergen Gross unsigned long lsize;
40b5d3c728SJuergen Gross };
41b5d3c728SJuergen Gross
42*961c6a43SJuergen Gross static struct mtrr_value *mtrr_value;
43b5d3c728SJuergen Gross
mtrr_save(void)44b5d3c728SJuergen Gross static int mtrr_save(void)
45b5d3c728SJuergen Gross {
46b5d3c728SJuergen Gross int i;
47b5d3c728SJuergen Gross
48*961c6a43SJuergen Gross if (!mtrr_value)
49*961c6a43SJuergen Gross return -ENOMEM;
50*961c6a43SJuergen Gross
51b5d3c728SJuergen Gross for (i = 0; i < num_var_ranges; i++) {
52b5d3c728SJuergen Gross mtrr_if->get(i, &mtrr_value[i].lbase,
53b5d3c728SJuergen Gross &mtrr_value[i].lsize,
54b5d3c728SJuergen Gross &mtrr_value[i].ltype);
55b5d3c728SJuergen Gross }
56b5d3c728SJuergen Gross return 0;
57b5d3c728SJuergen Gross }
58b5d3c728SJuergen Gross
mtrr_restore(void)59b5d3c728SJuergen Gross static void mtrr_restore(void)
60b5d3c728SJuergen Gross {
61b5d3c728SJuergen Gross int i;
62b5d3c728SJuergen Gross
63b5d3c728SJuergen Gross for (i = 0; i < num_var_ranges; i++) {
64b5d3c728SJuergen Gross if (mtrr_value[i].lsize) {
65b5d3c728SJuergen Gross mtrr_if->set(i, mtrr_value[i].lbase,
66b5d3c728SJuergen Gross mtrr_value[i].lsize,
67b5d3c728SJuergen Gross mtrr_value[i].ltype);
68b5d3c728SJuergen Gross }
69b5d3c728SJuergen Gross }
70b5d3c728SJuergen Gross }
71b5d3c728SJuergen Gross
72b5d3c728SJuergen Gross static struct syscore_ops mtrr_syscore_ops = {
73b5d3c728SJuergen Gross .suspend = mtrr_save,
74b5d3c728SJuergen Gross .resume = mtrr_restore,
75b5d3c728SJuergen Gross };
76b5d3c728SJuergen Gross
mtrr_register_syscore(void)77b5d3c728SJuergen Gross void mtrr_register_syscore(void)
78b5d3c728SJuergen Gross {
79*961c6a43SJuergen Gross mtrr_value = kcalloc(num_var_ranges, sizeof(*mtrr_value), GFP_KERNEL);
80*961c6a43SJuergen Gross
81b5d3c728SJuergen Gross /*
82b5d3c728SJuergen Gross * The CPU has no MTRR and seems to not support SMP. They have
83b5d3c728SJuergen Gross * specific drivers, we use a tricky method to support
84b5d3c728SJuergen Gross * suspend/resume for them.
85b5d3c728SJuergen Gross *
86b5d3c728SJuergen Gross * TBD: is there any system with such CPU which supports
87b5d3c728SJuergen Gross * suspend/resume? If no, we should remove the code.
88b5d3c728SJuergen Gross */
89b5d3c728SJuergen Gross register_syscore_ops(&mtrr_syscore_ops);
90b5d3c728SJuergen Gross }
91