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