]> Git Repo - J-u-boot.git/blame - arch/x86/cpu/mtrr.c
common: Drop net.h from common header
[J-u-boot.git] / arch / x86 / cpu / mtrr.c
CommitLineData
83d290c5 1// SPDX-License-Identifier: GPL-2.0+
aff2523f
SG
2/*
3 * (C) Copyright 2014 Google, Inc
4 *
aff2523f
SG
5 * Memory Type Range Regsters - these are used to tell the CPU whether
6 * memory is cacheable and if so the cache write mode to use.
7 *
8 * These can speed up booting. See the mtrr command.
9 *
10 * Reference: Intel Architecture Software Developer's Manual, Volume 3:
11 * System Programming
12 */
13
590cee83
SG
14/*
15 * Note that any console output (e.g. debug()) in this file will likely fail
16 * since the MTRR registers are sometimes in flux.
17 */
18
aff2523f 19#include <common.h>
9edefc27 20#include <cpu_func.h>
90526e9f 21#include <asm/cache.h>
aff2523f
SG
22#include <asm/io.h>
23#include <asm/msr.h>
24#include <asm/mtrr.h>
25
566d1754
BM
26DECLARE_GLOBAL_DATA_PTR;
27
aff2523f 28/* Prepare to adjust MTRRs */
590cee83 29void mtrr_open(struct mtrr_state *state, bool do_caches)
aff2523f 30{
3b621cca
BM
31 if (!gd->arch.has_mtrr)
32 return;
33
590cee83
SG
34 if (do_caches) {
35 state->enable_cache = dcache_status();
aff2523f 36
590cee83
SG
37 if (state->enable_cache)
38 disable_caches();
39 }
aff2523f
SG
40 state->deftype = native_read_msr(MTRR_DEF_TYPE_MSR);
41 wrmsrl(MTRR_DEF_TYPE_MSR, state->deftype & ~MTRR_DEF_TYPE_EN);
42}
43
44/* Clean up after adjusting MTRRs, and enable them */
590cee83 45void mtrr_close(struct mtrr_state *state, bool do_caches)
aff2523f 46{
3b621cca
BM
47 if (!gd->arch.has_mtrr)
48 return;
49
aff2523f 50 wrmsrl(MTRR_DEF_TYPE_MSR, state->deftype | MTRR_DEF_TYPE_EN);
590cee83 51 if (do_caches && state->enable_cache)
aff2523f
SG
52 enable_caches();
53}
54
6ccb2f89
SG
55static void set_var_mtrr(uint reg, uint type, uint64_t start, uint64_t size)
56{
57 u64 mask;
58
59 wrmsrl(MTRR_PHYS_BASE_MSR(reg), start | type);
60 mask = ~(size - 1);
61 mask &= (1ULL << CONFIG_CPU_ADDR_BITS) - 1;
62 wrmsrl(MTRR_PHYS_MASK_MSR(reg), mask | MTRR_PHYS_MASK_VALID);
63}
64
aff2523f
SG
65int mtrr_commit(bool do_caches)
66{
67 struct mtrr_request *req = gd->arch.mtrr_req;
68 struct mtrr_state state;
aff2523f
SG
69 int i;
70
590cee83
SG
71 debug("%s: enabled=%d, count=%d\n", __func__, gd->arch.has_mtrr,
72 gd->arch.mtrr_req_count);
3b621cca
BM
73 if (!gd->arch.has_mtrr)
74 return -ENOSYS;
75
590cee83
SG
76 debug("open\n");
77 mtrr_open(&state, do_caches);
78 debug("open done\n");
6ccb2f89
SG
79 for (i = 0; i < gd->arch.mtrr_req_count; i++, req++)
80 set_var_mtrr(i, req->type, req->start, req->size);
aff2523f
SG
81
82 /* Clear the ones that are unused */
590cee83 83 debug("clear\n");
aff2523f
SG
84 for (; i < MTRR_COUNT; i++)
85 wrmsrl(MTRR_PHYS_MASK_MSR(i), 0);
590cee83
SG
86 debug("close\n");
87 mtrr_close(&state, do_caches);
88 debug("mtrr done\n");
aff2523f
SG
89
90 return 0;
91}
92
93int mtrr_add_request(int type, uint64_t start, uint64_t size)
94{
95 struct mtrr_request *req;
96 uint64_t mask;
97
590cee83 98 debug("%s: count=%d\n", __func__, gd->arch.mtrr_req_count);
3b621cca
BM
99 if (!gd->arch.has_mtrr)
100 return -ENOSYS;
101
aff2523f
SG
102 if (gd->arch.mtrr_req_count == MAX_MTRR_REQUESTS)
103 return -ENOSPC;
104 req = &gd->arch.mtrr_req[gd->arch.mtrr_req_count++];
105 req->type = type;
106 req->start = start;
107 req->size = size;
108 debug("%d: type=%d, %08llx %08llx\n", gd->arch.mtrr_req_count - 1,
109 req->type, req->start, req->size);
110 mask = ~(req->size - 1);
111 mask &= (1ULL << CONFIG_CPU_ADDR_BITS) - 1;
112 mask |= MTRR_PHYS_MASK_VALID;
113 debug(" %016llx %016llx\n", req->start | req->type, mask);
114
115 return 0;
116}
add3f4c9
SG
117
118static int get_var_mtrr_count(void)
119{
120 return msr_read(MSR_MTRR_CAP_MSR).lo & MSR_MTRR_CAP_VCNT;
121}
122
123static int get_free_var_mtrr(void)
124{
125 struct msr_t maskm;
126 int vcnt;
127 int i;
128
129 vcnt = get_var_mtrr_count();
130
131 /* Identify the first var mtrr which is not valid */
132 for (i = 0; i < vcnt; i++) {
133 maskm = msr_read(MTRR_PHYS_MASK_MSR(i));
134 if ((maskm.lo & MTRR_PHYS_MASK_VALID) == 0)
135 return i;
136 }
137
138 /* No free var mtrr */
139 return -ENOSPC;
140}
141
142int mtrr_set_next_var(uint type, uint64_t start, uint64_t size)
143{
144 int mtrr;
145
146 mtrr = get_free_var_mtrr();
147 if (mtrr < 0)
148 return mtrr;
149
150 set_var_mtrr(mtrr, type, start, size);
151 debug("MTRR %x: start=%x, size=%x\n", mtrr, (uint)start, (uint)size);
152
153 return 0;
154}
This page took 0.278584 seconds and 4 git commands to generate.