xref: /openbmc/u-boot/arch/x86/cpu/mtrr.c (revision 3d5ced9e22d32112a20f9dc0f5fb1f22ef088079)
183d290c5STom Rini // SPDX-License-Identifier: GPL-2.0+
2aff2523fSSimon Glass /*
3aff2523fSSimon Glass  * (C) Copyright 2014 Google, Inc
4aff2523fSSimon Glass  *
5aff2523fSSimon Glass  * Memory Type Range Regsters - these are used to tell the CPU whether
6aff2523fSSimon Glass  * memory is cacheable and if so the cache write mode to use.
7aff2523fSSimon Glass  *
8aff2523fSSimon Glass  * These can speed up booting. See the mtrr command.
9aff2523fSSimon Glass  *
10aff2523fSSimon Glass  * Reference: Intel Architecture Software Developer's Manual, Volume 3:
11aff2523fSSimon Glass  * System Programming
12aff2523fSSimon Glass  */
13aff2523fSSimon Glass 
14*590cee83SSimon Glass /*
15*590cee83SSimon Glass  * Note that any console output (e.g. debug()) in this file will likely fail
16*590cee83SSimon Glass  * since the MTRR registers are sometimes in flux.
17*590cee83SSimon Glass  */
18*590cee83SSimon Glass 
19aff2523fSSimon Glass #include <common.h>
20aff2523fSSimon Glass #include <asm/io.h>
21aff2523fSSimon Glass #include <asm/msr.h>
22aff2523fSSimon Glass #include <asm/mtrr.h>
23aff2523fSSimon Glass 
24566d1754SBin Meng DECLARE_GLOBAL_DATA_PTR;
25566d1754SBin Meng 
26aff2523fSSimon Glass /* Prepare to adjust MTRRs */
mtrr_open(struct mtrr_state * state,bool do_caches)27*590cee83SSimon Glass void mtrr_open(struct mtrr_state *state, bool do_caches)
28aff2523fSSimon Glass {
293b621ccaSBin Meng 	if (!gd->arch.has_mtrr)
303b621ccaSBin Meng 		return;
313b621ccaSBin Meng 
32*590cee83SSimon Glass 	if (do_caches) {
33aff2523fSSimon Glass 		state->enable_cache = dcache_status();
34aff2523fSSimon Glass 
35aff2523fSSimon Glass 		if (state->enable_cache)
36aff2523fSSimon Glass 			disable_caches();
37*590cee83SSimon Glass 	}
38aff2523fSSimon Glass 	state->deftype = native_read_msr(MTRR_DEF_TYPE_MSR);
39aff2523fSSimon Glass 	wrmsrl(MTRR_DEF_TYPE_MSR, state->deftype & ~MTRR_DEF_TYPE_EN);
40aff2523fSSimon Glass }
41aff2523fSSimon Glass 
42aff2523fSSimon Glass /* Clean up after adjusting MTRRs, and enable them */
mtrr_close(struct mtrr_state * state,bool do_caches)43*590cee83SSimon Glass void mtrr_close(struct mtrr_state *state, bool do_caches)
44aff2523fSSimon Glass {
453b621ccaSBin Meng 	if (!gd->arch.has_mtrr)
463b621ccaSBin Meng 		return;
473b621ccaSBin Meng 
48aff2523fSSimon Glass 	wrmsrl(MTRR_DEF_TYPE_MSR, state->deftype | MTRR_DEF_TYPE_EN);
49*590cee83SSimon Glass 	if (do_caches && state->enable_cache)
50aff2523fSSimon Glass 		enable_caches();
51aff2523fSSimon Glass }
52aff2523fSSimon Glass 
mtrr_commit(bool do_caches)53aff2523fSSimon Glass int mtrr_commit(bool do_caches)
54aff2523fSSimon Glass {
55aff2523fSSimon Glass 	struct mtrr_request *req = gd->arch.mtrr_req;
56aff2523fSSimon Glass 	struct mtrr_state state;
57aff2523fSSimon Glass 	uint64_t mask;
58aff2523fSSimon Glass 	int i;
59aff2523fSSimon Glass 
60*590cee83SSimon Glass 	debug("%s: enabled=%d, count=%d\n", __func__, gd->arch.has_mtrr,
61*590cee83SSimon Glass 	      gd->arch.mtrr_req_count);
623b621ccaSBin Meng 	if (!gd->arch.has_mtrr)
633b621ccaSBin Meng 		return -ENOSYS;
643b621ccaSBin Meng 
65*590cee83SSimon Glass 	debug("open\n");
66*590cee83SSimon Glass 	mtrr_open(&state, do_caches);
67*590cee83SSimon Glass 	debug("open done\n");
68aff2523fSSimon Glass 	for (i = 0; i < gd->arch.mtrr_req_count; i++, req++) {
69aff2523fSSimon Glass 		mask = ~(req->size - 1);
70aff2523fSSimon Glass 		mask &= (1ULL << CONFIG_CPU_ADDR_BITS) - 1;
71aff2523fSSimon Glass 		wrmsrl(MTRR_PHYS_BASE_MSR(i), req->start | req->type);
72aff2523fSSimon Glass 		wrmsrl(MTRR_PHYS_MASK_MSR(i), mask | MTRR_PHYS_MASK_VALID);
73aff2523fSSimon Glass 	}
74aff2523fSSimon Glass 
75aff2523fSSimon Glass 	/* Clear the ones that are unused */
76*590cee83SSimon Glass 	debug("clear\n");
77aff2523fSSimon Glass 	for (; i < MTRR_COUNT; i++)
78aff2523fSSimon Glass 		wrmsrl(MTRR_PHYS_MASK_MSR(i), 0);
79*590cee83SSimon Glass 	debug("close\n");
80*590cee83SSimon Glass 	mtrr_close(&state, do_caches);
81*590cee83SSimon Glass 	debug("mtrr done\n");
82aff2523fSSimon Glass 
83aff2523fSSimon Glass 	return 0;
84aff2523fSSimon Glass }
85aff2523fSSimon Glass 
mtrr_add_request(int type,uint64_t start,uint64_t size)86aff2523fSSimon Glass int mtrr_add_request(int type, uint64_t start, uint64_t size)
87aff2523fSSimon Glass {
88aff2523fSSimon Glass 	struct mtrr_request *req;
89aff2523fSSimon Glass 	uint64_t mask;
90aff2523fSSimon Glass 
91*590cee83SSimon Glass 	debug("%s: count=%d\n", __func__, gd->arch.mtrr_req_count);
923b621ccaSBin Meng 	if (!gd->arch.has_mtrr)
933b621ccaSBin Meng 		return -ENOSYS;
943b621ccaSBin Meng 
95aff2523fSSimon Glass 	if (gd->arch.mtrr_req_count == MAX_MTRR_REQUESTS)
96aff2523fSSimon Glass 		return -ENOSPC;
97aff2523fSSimon Glass 	req = &gd->arch.mtrr_req[gd->arch.mtrr_req_count++];
98aff2523fSSimon Glass 	req->type = type;
99aff2523fSSimon Glass 	req->start = start;
100aff2523fSSimon Glass 	req->size = size;
101aff2523fSSimon Glass 	debug("%d: type=%d, %08llx  %08llx\n", gd->arch.mtrr_req_count - 1,
102aff2523fSSimon Glass 	      req->type, req->start, req->size);
103aff2523fSSimon Glass 	mask = ~(req->size - 1);
104aff2523fSSimon Glass 	mask &= (1ULL << CONFIG_CPU_ADDR_BITS) - 1;
105aff2523fSSimon Glass 	mask |= MTRR_PHYS_MASK_VALID;
106aff2523fSSimon Glass 	debug("   %016llx %016llx\n", req->start | req->type, mask);
107aff2523fSSimon Glass 
108aff2523fSSimon Glass 	return 0;
109aff2523fSSimon Glass }
110