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