xref: /OK3568_Linux_fs/u-boot/arch/x86/cpu/mtrr.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun  * (C) Copyright 2014 Google, Inc
3*4882a593Smuzhiyun  *
4*4882a593Smuzhiyun  * SPDX-License-Identifier:	GPL-2.0+
5*4882a593Smuzhiyun  *
6*4882a593Smuzhiyun  * Memory Type Range Regsters - these are used to tell the CPU whether
7*4882a593Smuzhiyun  * memory is cacheable and if so the cache write mode to use.
8*4882a593Smuzhiyun  *
9*4882a593Smuzhiyun  * These can speed up booting. See the mtrr command.
10*4882a593Smuzhiyun  *
11*4882a593Smuzhiyun  * Reference: Intel Architecture Software Developer's Manual, Volume 3:
12*4882a593Smuzhiyun  * System Programming
13*4882a593Smuzhiyun  */
14*4882a593Smuzhiyun 
15*4882a593Smuzhiyun #include <common.h>
16*4882a593Smuzhiyun #include <asm/io.h>
17*4882a593Smuzhiyun #include <asm/msr.h>
18*4882a593Smuzhiyun #include <asm/mtrr.h>
19*4882a593Smuzhiyun 
20*4882a593Smuzhiyun DECLARE_GLOBAL_DATA_PTR;
21*4882a593Smuzhiyun 
22*4882a593Smuzhiyun /* Prepare to adjust MTRRs */
mtrr_open(struct mtrr_state * state)23*4882a593Smuzhiyun void mtrr_open(struct mtrr_state *state)
24*4882a593Smuzhiyun {
25*4882a593Smuzhiyun 	if (!gd->arch.has_mtrr)
26*4882a593Smuzhiyun 		return;
27*4882a593Smuzhiyun 
28*4882a593Smuzhiyun 	state->enable_cache = dcache_status();
29*4882a593Smuzhiyun 
30*4882a593Smuzhiyun 	if (state->enable_cache)
31*4882a593Smuzhiyun 		disable_caches();
32*4882a593Smuzhiyun 	state->deftype = native_read_msr(MTRR_DEF_TYPE_MSR);
33*4882a593Smuzhiyun 	wrmsrl(MTRR_DEF_TYPE_MSR, state->deftype & ~MTRR_DEF_TYPE_EN);
34*4882a593Smuzhiyun }
35*4882a593Smuzhiyun 
36*4882a593Smuzhiyun /* Clean up after adjusting MTRRs, and enable them */
mtrr_close(struct mtrr_state * state)37*4882a593Smuzhiyun void mtrr_close(struct mtrr_state *state)
38*4882a593Smuzhiyun {
39*4882a593Smuzhiyun 	if (!gd->arch.has_mtrr)
40*4882a593Smuzhiyun 		return;
41*4882a593Smuzhiyun 
42*4882a593Smuzhiyun 	wrmsrl(MTRR_DEF_TYPE_MSR, state->deftype | MTRR_DEF_TYPE_EN);
43*4882a593Smuzhiyun 	if (state->enable_cache)
44*4882a593Smuzhiyun 		enable_caches();
45*4882a593Smuzhiyun }
46*4882a593Smuzhiyun 
mtrr_commit(bool do_caches)47*4882a593Smuzhiyun int mtrr_commit(bool do_caches)
48*4882a593Smuzhiyun {
49*4882a593Smuzhiyun 	struct mtrr_request *req = gd->arch.mtrr_req;
50*4882a593Smuzhiyun 	struct mtrr_state state;
51*4882a593Smuzhiyun 	uint64_t mask;
52*4882a593Smuzhiyun 	int i;
53*4882a593Smuzhiyun 
54*4882a593Smuzhiyun 	if (!gd->arch.has_mtrr)
55*4882a593Smuzhiyun 		return -ENOSYS;
56*4882a593Smuzhiyun 
57*4882a593Smuzhiyun 	mtrr_open(&state);
58*4882a593Smuzhiyun 	for (i = 0; i < gd->arch.mtrr_req_count; i++, req++) {
59*4882a593Smuzhiyun 		mask = ~(req->size - 1);
60*4882a593Smuzhiyun 		mask &= (1ULL << CONFIG_CPU_ADDR_BITS) - 1;
61*4882a593Smuzhiyun 		wrmsrl(MTRR_PHYS_BASE_MSR(i), req->start | req->type);
62*4882a593Smuzhiyun 		wrmsrl(MTRR_PHYS_MASK_MSR(i), mask | MTRR_PHYS_MASK_VALID);
63*4882a593Smuzhiyun 	}
64*4882a593Smuzhiyun 
65*4882a593Smuzhiyun 	/* Clear the ones that are unused */
66*4882a593Smuzhiyun 	for (; i < MTRR_COUNT; i++)
67*4882a593Smuzhiyun 		wrmsrl(MTRR_PHYS_MASK_MSR(i), 0);
68*4882a593Smuzhiyun 	mtrr_close(&state);
69*4882a593Smuzhiyun 
70*4882a593Smuzhiyun 	return 0;
71*4882a593Smuzhiyun }
72*4882a593Smuzhiyun 
mtrr_add_request(int type,uint64_t start,uint64_t size)73*4882a593Smuzhiyun int mtrr_add_request(int type, uint64_t start, uint64_t size)
74*4882a593Smuzhiyun {
75*4882a593Smuzhiyun 	struct mtrr_request *req;
76*4882a593Smuzhiyun 	uint64_t mask;
77*4882a593Smuzhiyun 
78*4882a593Smuzhiyun 	if (!gd->arch.has_mtrr)
79*4882a593Smuzhiyun 		return -ENOSYS;
80*4882a593Smuzhiyun 
81*4882a593Smuzhiyun 	if (gd->arch.mtrr_req_count == MAX_MTRR_REQUESTS)
82*4882a593Smuzhiyun 		return -ENOSPC;
83*4882a593Smuzhiyun 	req = &gd->arch.mtrr_req[gd->arch.mtrr_req_count++];
84*4882a593Smuzhiyun 	req->type = type;
85*4882a593Smuzhiyun 	req->start = start;
86*4882a593Smuzhiyun 	req->size = size;
87*4882a593Smuzhiyun 	debug("%d: type=%d, %08llx  %08llx\n", gd->arch.mtrr_req_count - 1,
88*4882a593Smuzhiyun 	      req->type, req->start, req->size);
89*4882a593Smuzhiyun 	mask = ~(req->size - 1);
90*4882a593Smuzhiyun 	mask &= (1ULL << CONFIG_CPU_ADDR_BITS) - 1;
91*4882a593Smuzhiyun 	mask |= MTRR_PHYS_MASK_VALID;
92*4882a593Smuzhiyun 	debug("   %016llx %016llx\n", req->start | req->type, mask);
93*4882a593Smuzhiyun 
94*4882a593Smuzhiyun 	return 0;
95*4882a593Smuzhiyun }
96